From 75ffc858fcff1effb785a589a0f7a659b54982b5 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 11 Feb 2010 21:57:24 +0000 Subject: [PATCH 001/293] Future public API for interfacing with WebKit on Haiku. (What will eventually become BWebView.) Compared to the original port, the threading has been completely redesigned such that all interaction with WebKit happens in the application thread, as required by the PThread threading backend. This is counteracted by using an offscreen BBitmap/view as the top-level GraphicsContext for each Page, such that drawing is performed in various app_server threads asynchronously. WebViewWindow provides as a target for messages from within WebKit (mostly FrameLoaderClientHaiku events), which are forwarded via virtual hook methods (implemented in LauncherWindow.cpp of the HaikuLauncher). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@6 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 68 +++++ src/apps/webpositive/DownloadWindow.h | 45 +++ src/apps/webpositive/Launcher.rdef | 254 +++++++++++++++++ src/apps/webpositive/LauncherApp.cpp | 250 +++++++++++++++++ src/apps/webpositive/LauncherApp.h | 62 +++++ src/apps/webpositive/LauncherWindow.cpp | 354 ++++++++++++++++++++++++ src/apps/webpositive/LauncherWindow.h | 91 ++++++ src/apps/webpositive/LeakTracker.h | 119 ++++++++ 8 files changed, 1243 insertions(+) create mode 100644 src/apps/webpositive/DownloadWindow.cpp create mode 100644 src/apps/webpositive/DownloadWindow.h create mode 100644 src/apps/webpositive/Launcher.rdef create mode 100644 src/apps/webpositive/LauncherApp.cpp create mode 100644 src/apps/webpositive/LauncherApp.h create mode 100644 src/apps/webpositive/LauncherWindow.cpp create mode 100644 src/apps/webpositive/LauncherWindow.h create mode 100644 src/apps/webpositive/LeakTracker.h diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp new file mode 100644 index 0000000000..b27acf86a9 --- /dev/null +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 "config.h" +#include "DownloadWindow.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +DownloadWindow::DownloadWindow(BRect frame) + : BWindow(frame, "Downloads", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) +{ + Minimize(true); + Show(); +} + +DownloadWindow::~DownloadWindow() +{ +} + +void DownloadWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + default: + BWindow::MessageReceived(message); + break; + } +} + +bool DownloadWindow::QuitRequested() +{ + if (!IsMinimized()) + Minimize(true); + return false; +} diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h new file mode 100644 index 0000000000..d263ddf387 --- /dev/null +++ b/src/apps/webpositive/DownloadWindow.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 DownloadWindow_h +#define DownloadWindow_h + +#include + +class DownloadWindow : public BWindow { +public: + DownloadWindow(BRect frame); + virtual ~DownloadWindow(); + + virtual void MessageReceived(BMessage*); + virtual bool QuitRequested(); + +private: +}; + +#endif // DownloadWindow_h + diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef new file mode 100644 index 0000000000..3165079460 --- /dev/null +++ b/src/apps/webpositive/Launcher.rdef @@ -0,0 +1,254 @@ +resource app_signature "application/x-vnd.RJL-HaikuLauncher"; + +resource app_version { + major = 0, + middle = 0, + minor = 1, + variety = B_APPV_ALPHA, + internal = 0, + short_info = "HaikuLauncher", + long_info = "HaikuLauncher ©2007-2010 The WebKit Haiku Project" +}; + +resource app_flags B_SINGLE_LAUNCH; + +resource file_types message { + "types" = "text/html", + "types" = "image/gif", + "types" = "image/jpeg", + "types" = "image/png", + "types" = "application/x-vnd.Be-bookmark", + "types" = "text", + "types" = "application/x-vnd.Be-doc_bookmark", + "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" + $"6B05000359463503C3A414039D816035000000000204BFC2B55BBBC5B55BC3BF" + $"B55BC6FABC93C6FAB896C6FAC090BFC2C3CBC3BFC3CBBBC5C3CBB88ABC93B88A" + $"C090B88AB896026EC5DCB8B6C713BAA0C4CAB706C110B579C307B5D5C0A2B565" + $"BFC2B55BC032B55BBDBCB55BBA69B7BABBC5B63AB8F9B94FB89DBD9CB84FBB7E" + $"B8C7BE9AB924BF77B8E0BEE7B9DEC11FBCE0C332BB38C279BEC5C405C2D8C31A" + $"C0FBC3FCC2C6C2C1C22FC2B7C27AC2BEC22FC2B7C227C2B7C227C2B7C227C2B7" + $"C241C2BDC241C2BDC206C2B0C199C2DBC1D0C2CBC159C2EEC0D4C2DDC115C2E5" + $"C051C2CEBF43C313BFB0C2B4BF3DC313BF36C313BF36C313BF36C313BF20C313" + $"BF20C313BF20C313BDEDC313BE23C313BDB9C2EDBD57C2DFBD87C2E3BD54C2DC" + $"BD3EC2C3BD3EC2C3BD31C2B4BD13C2A5BD26C2ABBD13C2A5BCA4C27EBCA4C27E" + $"BCA4C27EBC31C254BC31C254BC27C251BC12C24FBC1DC250BC10C24BBC0FC242" + $"BC11C246BC0FC242BBF5C219BBF5C219BBD3C1DEBB68C195BBAEC1A4BB71C16E" + $"BB58C129BB63C14EBB4BC101BB4BC0ADBB48C0D7BB4BC0ADBB4EC087BB4EC087" + $"BB52C054BB4DBFEEBB55C021BB9EBF93BBA9BEBFBBB0BF36BBA9BEBFBBA7BE93" + $"BBA7BE93BBA7BE53BBBCBE2FBBA8BE4BBBBCBE2FBBC7BE21BBC7BE21BC00BDD5" + $"BBE3BCFCBC5BBD3DBBE3BCFCBAB7BC58BAB7BC58BAB7BC58BA8BBC44BA90BC46" + $"BA8BBC44BA8BBC42BA8BBC42BA89BBEABA23BB79BA6ABBADBA23BB79BA12BB6B" + $"BA12BB6BBA12BB6BB9F8BB49B9F8BB49B9F8BB49B9AEBAF0B9AEBAF0B97EBAC3" + $"B928BAB1B950BAB5B924BAA9B91BBA9AB920BAA1B984BA6EB9DEB997B9B5B9F9" + $"B9F6B95DBA36B8F0BA0BB91FBA5EB8C4BA78B85EBA83B89EBACCB83DBB61B7E7" + $"BB18B813BB61B7E7BB6BB7E1BB6BB7E1BB6BB7E1BBFEB787BBFEB787BC65B74A" + $"BCB6B684BC94B6F6BCF5B68ABD58B665BD2DB67BBDA8B695BE6DB651BE29B697" + $"BE6FB650BE88B64FBE7CB64FBE62B6A0BEE1B72FBE88B70EBEE4B733BEE9B73E" + $"BEE5B73ABED8B744BEC6B74ABEC6B74ABEC6B74ABE75B7A5BE75B7A5BE63B7DD" + $"BE90B849BE74B817BE91B84CBE92B852BE92B852BE94B85CBE9DB87ABE97B86B" + $"BE94B884BE8CB88DBE8CB88DBE3AB8F0BD92B98FBDB7B906BD92B98FBD8DB9A1" + $"BD8DB9A1BD64B9D8BD7EBA55BD59BA19BD7BBA5CBD77BA63BD77BA63BD56BAA0" + $"BD4DBB2CBD39BAE6BD60BB70BDCCBBCEBD98BBA2BDFFBBFABE73BC3FBE33BC27" + $"BEBEBC5CBF5EBC42BF12BC56BF5EBC42BFAC37BFAC37BFD0BC1EC01CBC0FBFF5" + $"BC0BC046BC14C083BC4EC066BC35C04DBCD9C0F4BDDAC0B6BD63C0F4BDDAC107" + $"BDF9C102BDF2C0BABE84C127BF91C0B2BF1DC127BF91C133BF9DC133BF9DC131" + $"C00FC1C5C0F9C135C0D6C259C11CC348C059C2EEC0C9C348C059C36BC02FC36B" + $"C02FC36BC02FC388C019C388C019C3A8C003C3DBBFC5C3C9BFE8C3EEBFA0C409" + $"BF52C3F0BF73C409BF52C409BF53C409BF53C40DBF9AC495BFC1C450BFCEC4EB" + $"BFB3C542BF10C51FBF56C542BF10C551BEF2C551BEF2C551BEF2C555BEEBC555" + $"BEEBC57FBEA3C568BDFCC59EBE47C53ABDBBC4A3BDDFC4E1BDAAC4A3BDCAC4A3" + $"BDB5C4A3BDB5C4A3BDB5C4A5BD31C4A5BD31C4A8BD1EC4E8BCDFC4D2BCF5C4E8" + $"BCDFC4FEBCC9C4FEBCC9C4FEBCC9C516BCB3C516BCB3C545BC8BC582BC20C571" + $"BC5EC58CBC05C588BBBCC586BBD9C588BBBCC587BBA8C587BBA8C587BBA8C588" + $"BB9DC588BB9DC58DBB614EBAFAC584BB24C58ABADAC5C2BA5DC5B0BAA2C5C4BA" + $"62C5CBBA70C5CBBA70C5D9BA8EC60FBAD4C5EDBAB3C60ABB1FC648BBAAC627BB" + $"67C669BBEBC66FBC7BC670BC33C66FBC7BC672BCC4C672BCC4C674BCEAC66EBD" + $"37C678BD11C664BD5AC649BD9CC652BD79C633BDECC62CBE92C62DBE3FC621BE" + $"D5C67FBF2CC648BF16C750BD0F0006BC12B6E4BC12B6E4BC32B6B0BC55B638BC" + $"47B674BB81B6ABBA2BB802BAC4B747BA88B7E3BB30B77EBADDB7B0BB59B765BB" + $"AAB733BB82B74DBBCBB71DBC12B6E4BBFCB707BC12B6E4001DBACDBFD1BACDBF" + $"D1BAEBBFAABB29BF5CBB13BF89BB43BF24BB34BE93BB34BED0BB34BE4DBB60BD" + $"EABB34BE25BB80BDBEBBABBD60BBA1BD98BB48BD2ABA81BCBEBAE5BCF3BA67BC" + $"B1BA20BC83BA2DBCA0BA0FBC5BBA0DBC02BA1FBC28B9FEBBE5B9BABBB6B9D0BB" + $"D0B99BBB91B95FBB44B983BB66B93DBB24B8F0BB2DB91CBB16B8C0BB48B8BEBA" + $"DFB8C3BAFFB8B1BB14B89FBB7EB8A7BB49B8C9BB7EB8C5BBB2B8C3BB8AB8C6BB" + $"DBB8C9BC2EB8C7BC05B8D0BC40B8BABC49B8CBBC49B8B4BC4BB8AABC4EB8AFBC" + $"4DB8A0BC57B893BC4BB898BC56B882BC4AB88FBD10B88EBD00B893BD49B8E1BD" + $"E7B88DBE03B90DBE04B923BE75B906BE4BB946BEA8B985BF00B973BEC1B997BF" + $"3EB9A3BFC1B998BF81B9B0C011BA17C05FB9DBC02EBA25C0B3BA75C127BA3DC0" + $"E7BA8FC144BAC0C17FBAA9C160BAD8C19FBAFCC17CBAE4C19DBADDC13ABAD7C0" + $"A6BAD3C0EFBADBC061BACDBFD1BAEAC013BACDBFD10009BD5EB5D7BD5EB5D7BD" + $"81B5EEBDB1B60EBD84B605BDD0B613BE19B601BE01B61ABE55B5C3BEF6B5C4BE" + $"B0B5EFBF2DB5A2BFA3B55EBF5BB55EBFCEB55DC00CB58CBFE9B578C03CB5A7C0" + $"90B566C064B575BF3AB541BCA7B60EBDDDB57ABCECB623BD5EB5D7BD29B601BD" + $"5EB5D70005BF35B6EABF35B6EABF55B6ECBF9AB6F5BF7BB702BFCEB6E0BF87B6" + $"7DBF9CB693BF78B66DBF3CB664BF2FB623BF45B690BF35B6EABF6BB6CCBF35B6" + $"EA0004BA07B87FBA07B87FBA0CB868B9EFB850B9FEB85FB982B8E4B8F0BA35B9" + $"2CB988B97E31BA07B87FB974B8F0BA07B87F0066C6F7BC24C6F7BC24C6DCBB0A" + $"C6002FC68BB9F2C5B9B87CC4FFB79CC563B805C4CEB768C463B709C49AB737C4" + $"52B6FBC428B6EFC440B6E2C412B6FAC407B6C1C401B6D1C316B60FC0D0B56FC1" + $"F9B59AC0FBB58BC15FB59CC131B589C170B5A2C179B5C9C19FB5BDC12DB5E2C0" + $"8AB5C9C0D7B5C4C05AB5CDC03FB60EC043B5DDC03DB629C040B676C036B65DC0" + $"4BB694C0B6B65FC0A8B66FC0CDB643C0F1B61AC0B1B608C108B64BC0D0B6B1C1" + $"3AB6D6C0B5B6A7C066B689C083B67CC064B68AC05DB6AFC05FB6ABC053B6C0C0" + $"31B6D0C044B6CBBFE6B6E5BF94B741BFB0B6EFBF87B769BF5DB791BF88B781BF" + $"3BB79DBEF7B7B2BF17B7A4BECCB7C7BEFAB81CBEEAB7FFBF06B830BF19B86CBF" + $"03B860BF59B891BFBEB7E0BFA3B802BFE1B7B3C038B7ADC008B7BDC04FB7A6C0" + $"84B777C06CB76EC0D3B795C0F8B83EC0EBB7F4C110B83FC135B810C100B802C1" + $"0DB7E5C0ECB77043B7ABC125B795C15FB7FDC14DB7BDC170B83DC1C2B820C18E" + $"B860C1CFB813C1FDB7D5C1E2B7BDC214B7EAC1F1B838C215B82FC206B84BC23A" + $"B83DC222B843C25AB834C28BB842C26CB836C2AFB850C2FAB857C2D5B854C320" + $"B859C347B898C335B87BC377B8E7C24AB8C5C259B8C6C228B8C3C1E2B8D0C202" + $"B8C2C1C9B8DAC199B8F0C1B62FC179B8E5C13FB8B6C15BB8C8C118B89CC0C5B8" + $"72C0EFB885C07FB853BFE3B84FC02FB83FBFBFB856BF7FB87CBF9CB866BF5CB8" + $"97BF11B8A4BF35B87FBEDCB8DCBE6EB942BEB6B91FBE51B950BE19B976BE2EB9" + $"5CBE04B990BDF6B9D1BE04B9B4BDE9B9EEBDE2BA1DBDCAB9FCBDF8BA3CBDEFBA" + $"76BDFEBA53BDD9BAA9BDC9BB27BD9FBAEFBDF235BE71BBBCBE3ABB94BEAFBBE9" + $"BF41BBD2BEFBBBE5BF83BBC1C009BB9CBFC5BBA1C05FBB96C0DDBC03C0A1BBCD" + $"C104BC26C0F5BC67C114BC34C0D3BC9FC103BD00C0E8BCC8C11FBD37C159BDA3" + $"C13CBD6DC166BDBAC182BDE8C177BDD0C18EBE04C16DBE2DC17BBE15C152BE5E" + $"C13FBECFC13FBE97C13FBF0EC185BF4CC15DBF24C1AABF71C1A4BFE3C1A8BFB3" + $"C1A0C025C1DBC087C1B3C053C216C08AC289C06CC253C086C2CBC04DC319BFDE" + $"C2E8C00FC347BFB0C386BF66C378BFABC396BF13C3FEBEBFC3C2BEF2C435BE90" + $"C430BE0CC42EBE4DC432BDC0C433BD22C429BD6DC43CBCDEC4ABBC78C47EBCA7" + $"C4CDBC56C512BC03C505BC34C519BBE7C513BBA8C51336C513BB93C51135C51A" + $"BB71C4F8BB29C47EBB2CC48ABB5DC476BB0EC48BBB01C477BB14C4A1BAEDC478" + $"BACDC48BBAD8C442BAADC3F1BA66C418BA9AC3CCBA36C391B9CBC3AEBA00C389" + $"B9BEC36CB93BC342B92EC39AB94AC3E2B9A3C3C4B981C419B9DFC46DBA6AC44A" + $"BA20C46EBA73C496BA8AC48FBA85C4AFBA9CC4EABAA8C4CABAABC533BAA2C55A" + $"BA20C555BA61C562B9C7C4E8B9AFC51DB9DAC4CAB997C49EB958C4B6B975C48F" + $"B946C474B90EC466B92AC493B8F9C4BDB91DC49FB90BC4E0B932C52CB951C505" + $"B944C555B95EC5B4B96CC592B952C5C9B97CC5E7B9B8C5D9B9A2C5FEB9DCC627" + $"BA26C614BA00C645BA61C694BA9FC64DBA89C667BAE8C6B6BB83C693BB3FC6DF" + $"BBD4C6E3BC7CC6E4BC23C6E2BCCEC6D0BD79C6F5BD2CC6A7BDCCC69FBE9AC69F" + $"BE3EC6A1BE95C6A5BE88C6A3BE8DC6A2BE8FC6A1BEC0C696BEBEC6B2BEC4C6D6" + $"BE02C6D2BE15C6F6BD65C6F7BC24C700BCC4C6F7BC240008C301B7D8C301B7D8" + $"C2E6B7DCC2D4B7A4C2E8B7AEC2B1B792C269B7B8C288B7A7C204B7EFC236B743" + $"C221B77BC239B73AC285B744C27AB746C2A7B740C2F3B74FC2D8B731C30CB76B" + $"C33CB7A1C31FB787C360B7C2C301B7D8C31CB7D4C301B7D80004BB53C203BB53" + $"C203BB45C20DBB26C221BB38C21DBB55C249BBBAC291BB87C26EBB92C265BB53" + $"C203BB84C227BB53C2030005C4F4BE2EC4F4BE2EC4D3BE57C48CBEA4C4A6BE76" + $"C46EBEDAC47DBF53C47DBF18C4B6BF38C4EDBEB9C4D0BEECC502BE93C4F4BE2E" + $"C531BE48C4F4BE2E0009C213C327C213C327C17FC390BFF7C345C09DC332BFD0" + $"C349BF8EC36ABFACC350BF67C38CBF20C386BF56C386BEAFC386BDCDC386BE3E" + $"C386BEC1C3CBC0C0C3BABFC4C3DDC137C3AAC221C367C1AFC38EC22AC364C262" + $"C32BC280C337C249C322C213C327C22AC331C213C32702024E284E2C542E4C32" + $"4C30482E020250304C3252344C364E344C340202C951B81858305C3254365432" + $"4E300202583456365836563C5A3854380204BCD6C1F1BACDC370BEA5C09BC4A7" + $"BFA6C361BE3CC67FC1B1C065C5ADC23AC445BE91C715B827C85DB962C9B9B682" + $"C68C0204C3CFC072C309BF46C522C2743DC65FC0DEC4E4BC10C7F7B880C76BB8" + $"DAC831B842C6E2BC70C2E3B880C5CDBE43C189061EAEE6BAEAAAAF9A0EB9E5C6" + $"DFB9CC50B985C673BA12C5CDBAE4C593BA9EC0BFBC89BE0E36B8E6B993B8DA2E" + $"B874B92DB971B7B0BCD6BA52BCEFB87ABE3BB7AEBD62B7AEBF13B7AEBF862EBF" + $"93BA78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF" + $"A0BDCEBFCCC18BC1FDC323BF00C13E46C33BC197C43B46C3DCC12BC484C02CC4" + $"94C012C3EFC092C36FBE21C2BDBF40BC50C14BBBF74EBB8451BBE8C66FBA9EC6" + $"B90611AAAAA8BA02BBF0B9ECBB4ABAB8BCC9BB9DBCE2BE4EBB71C019BC7CC0A5" + $"BE08BF73BE6144BFA0BF6DBDDBC06CBD0245BCAFC1CABC30BF40BAABBE0EBB04" + $"BF0DBB04BD83BB04BD15BAB8BCAFBA38060BBAAA2A31C653BA0CC6C5BB84C646" + $"BB2BC69FBBB6C614BBB0C5A0BBDDC309BC1DC164BCAFC0CBBB71BFE6BAD8C0CB" + $"BACBC395BAE4C5C6060AAAAB0ABE47C125BF99C131BF80454448C1FDC395C21D" + $"C362C1C4C3F1C11EC448C052C494C02CC3EFC105C389BE67470605EA02BB37BA" + $"C5BBD7BA12B9ACB887B8E0B8ADB90BB86AB887B939B920B96C0A05C16BBB91C4" + $"74BB91C4DABC36C4A7BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF" + $"4DBA45BE0EBB04BEA7BB2BBD8ABAE3BD29BA520607AA3A39B8EDBE012F3CB99F" + $"3EB993BEDAB920BF99B946BE34B77BBFF6B7C339B74804032EBCE932BDCEBB2B" + $"BD34BB13BECDBB51BF4DBA380208CA68BA5FCB41BD02CA3AB9D0CA0FB6BCCAF4" + $"B7AEC947B5E955B58A55B58A55B58AC844B841C8FFB76C53B953C718B814C6E6" + $"B8FBC74BB728C5A02FC601B84FC2703DC646BCB6C5ADBC1DC712BD82C89DBEE7" + $"C79E40C89DBEE7060ABFFB0FC6F2C098C626BFCCC6F2BFCC5A345C3758315A2E" + $"5A305A2C582A562E582C54305230C692B854C692B920C692B7DAC53ABAAB4FB9" + $"ACC501BB1EC46EBBF7C4AEBB9DC3FBBCB6C56DBE0EC38FBE4EC64DBDF00207C8" + $"70BE74C870BE74C7A4BDA8C78BBB44C80BBB28C71835C633BBB7C6D5BBF0C5DB" + $"BB98C501BB44C50ABB7AC4F2BAEEC3F5BC43C43FBBD2C4B4BC83C6FF38C63336" + $"C7CB3AC83DBE9AC5B3BF8DC909BD020202C6392F4DB9F9C66CBAC54DBBE34FBB" + $"17C46EBAEB0202C969B7CEC967B916CAFFB9E2543654324E3002025834563658" + $"36C877BD8FC969BB84C7ABBBF70604EAC2BD4448C111C32FC07FC362C17EC33C" + $"C0E5C37CC1E40205C5ADB861C65F31C52CB75E50204E224E20C3E2BA5FC37CB9" + $"50C455BB91C606BD02C494BCB6C723BE0DCB1BBDA8CB97BDE4C79EBBF702044E" + $"B44BC4D4284EB5174BB9B9C408B8BAC43EBAD855BD4F4BBBD057BD4FC745BB77" + $"C818BC3C51BAC502034E28C4A1B847C53AB61650BA52C593B8A0C691BBAFC4E1" + $"BAAB59BD8FC4E1B7A104032EB77BC613B63CC969B50AC7ABB778CB36BCA9C99C" + $"04032EB966B906B953B7D4B8D3B86DB9C7B749BAB82C0406BE0BB689BE67B5FD" + $"C04CB608BF7FB5F1C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C3" + $"1EB70849B609C32304032EBDA8B887BEB4B76EBE11B775BFEC2BC059B8AD0403" + $"2E28BE01B3FFC0D8B4253FB3D3C288B5BDC2FC0406FE0BC79EBB2BC8F6BBAAC8" + $"41BB48C9ECBC2FCB27BDDBCB06BD15CB41BE74CA4FC07FCA99BFCBCA0FC118C9" + $"CFC27DCA0FC1E4C998C30058C3890A04C6FFBB11C857BC50C8BDBCC3C88ABD4F" + $"040CAAFABABC70C74BC092C699C303C5CDC3DBC54DC441C4CEC44EC382C1EAC3" + $"03C237C34DC1D5C2EEC05FC402C14AC3E0BF76C423BD88C461BD48C4FABE47C5" + $"14BE2E4DBE98C58CBDBBC5870608BAAABFECC1FD4448C1FDC395C21DC362C1C4" + $"C3F1C11EC448C052C494C02CC3EFC105C389BED4C2BD0A04C369BC83C6D838C6" + $"66BD1CC35CBD350A03B46542B4BE41B4BE420605AF03B6AFC969B63DC9F2B72F" + $"C8D0BE4155B821CA8EC11CC6FAC42EC5C6C560C53ABE67C91DC1E8C7EAB86DCB" + $"270604EEBFCCBB51C1FDBBD0C13EBC43C29FBB6FC18BBAAB43BB1EC146BAF2C0" + $"9ABB4B0A0430303050505050302C0A0001021240BAB100000000000040B755C6" + $"CCDBBE997901178300040A0101020240BAB100000000000040B755C6CCDBBE99" + $"790A0201030240BAB100000000000040B755C6CCDBBE99790A030A0506070809" + $"0A0C0D040B0240BAB100000000000040B755C6CCDBBE99790A11011312408447" + $"3AE65BBB0539406A8F40BD7AC6ED3001178400040A00012712401CCA00000000" + $"00004031D6BEA7B4C5651401178100040A150112024046733A7FB6BABB054015" + $"08437714C3BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF" + $"0A11011412402E52374883B74883402E5243A84DC5C35901178200040A160115" + $"02402E52374883B74883402E5243A84DC5C3590A17011602402E52374883B748" + $"83402E5243A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3" + $"590A17011802402E52374883B74883402E5243A84DC5C3590A1801190240268F" + $"36C1F1B73CD33FA9DD442903C369B00A1B011A02402E52374883B74883402E52" + $"43A84DC5C3590A2C011B02402E52374883B74883402E5243A84DC5C3590A1101" + $"1C12402E52374883B74883402E5243A84DC5C35901178100040A20011D124018" + $"A13C2DD3BC6F843F776243040C3B35B701178400040A28011D024018A13C481B" + $"BC6F843FA13143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0C" + $"BDA6830A2603212022023F94B53C057BBC14913F373546DE4E423FFC0A2B0122" + $"02401CCA000000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97" + $"FB40685AC6A141CA33220A0001291240075E0000000000004029CCC0DC88C59D" + $"5C01178100040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D011784" + $"00040A360124023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4" + $"F539818BBA43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A" + $"55C7EFC8485E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D2660117" + $"8200040A00012A12402E52374883B74883402E5241C554C5CE0401178100040A" + $"00012B12401CCA000000000000401CCAC0623FC4B46E01178100040A00012C12" + $"403196000000000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA00" + $"0000000000401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0" + $"E971C4B46E1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF" + $"0A3E01310240FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA00" + $"0000000000401CCAC0E971C42D3C01178200040A4001330A401CCA0000000000" + $"00401CCAC0E971C4B46E1DFF0A42013402360000000000000000360000489000" + $"4AE8000A420134023600000000000000003600004870004AE8000A4301340236" + $"00000000000000003600004850004AF8000A4301340236000000000000000036" + $"00004870004AF8000A430134023600000000000000003600004890004AF8000A" + $"44013402360000000000000000360000485000466000" +}; + diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp new file mode 100644 index 0000000000..74b8d84fca --- /dev/null +++ b/src/apps/webpositive/LauncherApp.cpp @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2010 Stephan Aßmus + * + * 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 "config.h" +#include "LauncherApp.h" + +#include "FrameView.h" +#include "GraphicsContext.h" +#include "LauncherWindow.h" +#include "WebProcess.h" +#include "WebView.h" +#include "WebViewConstants.h" + +#include +#include +#include +#include +#include +#include + +#include + +extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; +enum { + LOAD_AT_STARTING = 'lost' +}; + + +LauncherApp::LauncherApp() + : BApplication(kApplicationSignature) + , m_lastWindowFrame(100, 100, 700, 750) + , m_launchRefsMessage(0) + , m_initialized(false) +{ +} + +LauncherApp::~LauncherApp() +{ + delete m_launchRefsMessage; +} + +void LauncherApp::AboutRequested() +{ + BAlert* alert = new BAlert("About HaikuLauncher", + "For testing WebKit...\n\nby Ryan Leavengood", "Sweet!"); + alert->Go(); +} + +void LauncherApp::ArgvReceived(int32 argc, char** argv) +{ + for (int i = 1; i < argc; i++) { + BMessage message(LOAD_AT_STARTING); + message.AddString("url", argv[i]); + message.AddBool("new window", m_initialized || i > 1); + PostMessage(&message); + } +} + +void LauncherApp::ReadyToRun() +{ + WebProcess::initializeOnce(); + + BFile settingsFile; + BRect windowFrameFromSettings = m_lastWindowFrame; + if (openSettingsFile(settingsFile, B_READ_ONLY)) { + BMessage settingsArchive; + settingsArchive.Unflatten(&settingsFile); + settingsArchive.FindRect("window frame", &windowFrameFromSettings); + } + m_lastWindowFrame = windowFrameFromSettings; + + m_initialized = true; + + if (m_launchRefsMessage) { + RefsReceived(m_launchRefsMessage); + delete m_launchRefsMessage; + m_launchRefsMessage = 0; + } else { + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + window->Show(); + } +} + +void LauncherApp::MessageReceived(BMessage* message) +{ + switch (message->what) { + case LOAD_AT_STARTING: { + BString url; + if (message->FindString("url", &url) != B_OK) + break; + bool newWindow; + if (message->FindBool("new window", &newWindow) != B_OK) + newWindow = false; + WebViewWindow* webWindow = NULL; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!newWindow) { + // stop at the first window + break; + } + } + if (webWindow) { + // There should always be at least one window open. If not, maybe we are about + // to quit anyway... + if (newWindow) { + // open a new window with an offset to the last window + webWindow->newWindowRequested(url); + } else { + // load the URL in the first window + webWindow->webView()->loadRequest(url.String()); + } + } + break; + } + case B_SILENT_RELAUNCH: + newWindow(""); + break; + case NEW_WINDOW: { + BString url; + if (message->FindString("url", &url) != B_OK) + break; + newWindow(url); + break; + } + case WINDOW_OPENED: + m_windowCount++; + break; + case WINDOW_CLOSED: + m_windowCount--; + message->FindRect("window frame", &m_lastWindowFrame); + if (m_windowCount <= 0) + PostMessage(B_QUIT_REQUESTED); + break; + + default: + BApplication::MessageReceived(message); + break; + } +} + +void LauncherApp::RefsReceived(BMessage* message) +{ + if (!m_initialized) { + delete m_launchRefsMessage; + m_launchRefsMessage = new BMessage(*message); + return; + } + + 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(); + newWindow(url); + } +} + +bool LauncherApp::QuitRequested() +{ + for (int i = 0; BWindow* window = WindowAt(i); i++) { + WebViewWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!webWindow->Lock()) + continue; + if (webWindow->QuitRequested()) { + m_lastWindowFrame = webWindow->Frame(); + webWindow->Quit(); + i--; + } else { + webWindow->Unlock(); + return false; + } + } + + BFile settingsFile; + if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + BMessage settingsArchive; + settingsArchive.AddRect("window frame", m_lastWindowFrame); + settingsArchive.Flatten(&settingsFile); + } + + return true; +} + +bool LauncherApp::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + +void LauncherApp::newWindow(const BString& url) +{ + m_lastWindowFrame.OffsetBy(20, 20); + if (!BScreen().Frame().Contains(m_lastWindowFrame)) + m_lastWindowFrame.OffsetTo(50, 50); + + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + window->Show(); + if (url.Length()) + window->webView()->loadRequest(url.String()); +} + +// #pragma mark - + +int main(int, char**) +{ + new LauncherApp(); + be_app->Run(); + delete be_app; + + return 0; +} + diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h new file mode 100644 index 0000000000..8afdfc4192 --- /dev/null +++ b/src/apps/webpositive/LauncherApp.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * + * 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 LauncherApp_h +#define LauncherApp_h + +#include +#include + +class BFile; +class LauncherWindow; + +class LauncherApp : public BApplication { +public: + LauncherApp(); + virtual ~LauncherApp(); + + virtual void AboutRequested(); + virtual void ArgvReceived(int32, char**); + virtual void MessageReceived(BMessage*); + virtual void RefsReceived(BMessage*); + virtual void ReadyToRun(); + virtual bool QuitRequested(); + +private: + bool openSettingsFile(BFile& file, uint32 mode); + void newWindow(const BString& url); + + int m_windowCount; + BRect m_lastWindowFrame; + BMessage* m_launchRefsMessage; + bool m_initialized; +}; + +extern const char* kApplicationSignature; + +#endif // LauncherApp_h + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp new file mode 100644 index 0000000000..2407f34b45 --- /dev/null +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2007 Andrea Anzani + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2009 Maxime Simon + * Copyright (C) 2010 Stephan Aßmus + * + * 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 "config.h" +#include "LauncherWindow.h" + +#include "WebView.h" +#include "WebViewConstants.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum { + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + GOTO_URL = 'goul', + RELOAD = 'reld', + + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', + + TEXT_SHOW_FIND_GROUP = 'sfnd', + TEXT_HIDE_FIND_GROUP = 'hfnd', + TEXT_FIND_NEXT = 'fndn', + TEXT_FIND_PREVIOUS = 'fndp' +}; + +using namespace WebCore; + +static BLayoutItem* layoutItemFor(BView* view) +{ + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); +} + +LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) + : WebViewWindow(frame, "HaikuLauncher", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) +{ + if (toolbarPolicy == HaveToolbar) { + // Menu + m_menuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + m_menuBar->AddItem(menu); + + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + m_menuBar->AddItem(menu); + + // Back & Forward + m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); + m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); + + // URL + m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); + m_url->SetDivider(50.0); + + // Go + BButton* button = new BButton("", "Go", new BMessage(RELOAD)); + + // Status Bar + m_statusText = new BStringView("status", ""); + m_statusText->SetAlignment(B_ALIGN_LEFT); + m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + m_statusText->SetExplicitMinSize(BSize(150, 16)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + m_statusText->SetFont(&font, B_FONT_SIZE); + + // Loading progress bar + m_loadingProgressBar = new BStatusBar("progress"); + m_loadingProgressBar->SetMaxValue(100); + m_loadingProgressBar->Hide(); + m_loadingProgressBar->SetBarHeight(10); + + const float kInsetSpacing = 5; + const float kElementSpacing = 7; + + m_findTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(m_findTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(m_findCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(m_menuBar) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(m_BackButton, 0, 0) + .Add(m_ForwardButton, 1, 0) + .Add(m_url, 2, 0) + .Add(button, 3, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(webView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(m_statusText) + .Add(m_loadingProgressBar, 0.2) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) + ); + + m_url->MakeFocus(true); + + m_findGroup = layoutItemFor(findGroup); + } else { + m_BackButton = 0; + m_ForwardButton = 0; + m_url = 0; + m_menuBar = 0; + m_statusText = 0; + m_loadingProgressBar = 0; + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) + .Add(webView()) + ); + } + + m_findGroup->SetVisible(false); + + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); + AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); + AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + + navigationCapabilitiesChanged(false, false, false); + + be_app->PostMessage(WINDOW_OPENED); +} + +LauncherWindow::~LauncherWindow() +{ +} + +void LauncherWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case RELOAD: + webView()->loadRequest(m_url->Text()); + break; + case GOTO_URL: + if (m_loadedURL != m_url->Text()) + webView()->loadRequest(m_url->Text()); + break; + case GO_BACK: + webView()->goBack(); + break; + case GO_FORWARD: + webView()->goForward(); + break; + + case TEXT_SIZE_INCREASE: + webView()->increaseTextSize(); + break; + case TEXT_SIZE_DECREASE: + webView()->decreaseTextSize(); + break; + case TEXT_SIZE_RESET: + webView()->resetTextSize(); + break; + + case TEXT_FIND_NEXT: + webView()->findString(m_findTextControl->Text(), true, + m_findCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + webView()->findString(m_findTextControl->Text(), false, + m_findCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!m_findGroup->IsVisible()) + m_findGroup->SetVisible(true); + m_findTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (m_findGroup->IsVisible()) + m_findGroup->SetVisible(false); + break; + + default: + WebViewWindow::MessageReceived(message); + break; + } +} + +bool LauncherWindow::QuitRequested() +{ + if (WebViewWindow::QuitRequested()) { + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; + } + return false; +} + +// #pragma mark - Notification API + +void LauncherWindow::navigationRequested(const BString& url) +{ + m_loadedURL = url; + if (m_url) + m_url->SetText(url.String()); +} + +void LauncherWindow::newWindowRequested(const BString& url) +{ + // Always open new windows in the application thread, since + // creating a WebView will try to grab the application lock. + // But our own WebProcess may already try to lock us from within + // the application thread -> dead-lock. + BMessage message(NEW_WINDOW); + message.AddString("url", url); + be_app->PostMessage(&message); +} + +void LauncherWindow::loadNegociating(const BString& url) +{ + BString status("Requesting: "); + status << url; + statusChanged(status); +} + +void LauncherWindow::loadTransfering(const BString& url) +{ + BString status("Loading: "); + status << url; + statusChanged(status); +} + +void LauncherWindow::loadProgress(float progress) +{ + if (m_loadingProgressBar) { + if (progress < 100 && m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Show(); + m_loadingProgressBar->SetTo(progress); + } +} + +void LauncherWindow::loadFailed(const BString& url) +{ + BString status(url); + status << " failed."; + statusChanged(status); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); +} + +void LauncherWindow::loadFinished(const BString& url) +{ + m_loadedURL = url; + BString status(url); + status << " finished."; + statusChanged(status); + if (m_url) + m_url->SetText(url.String()); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); +} + +void LauncherWindow::titleChanged(const BString& title) +{ + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); +} + +void LauncherWindow::statusChanged(const BString& statusText) +{ + if (m_statusText) + m_statusText->SetText(statusText.String()); +} + +void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop) +{ + if (m_BackButton) + m_BackButton->SetEnabled(canGoBackward); + if (m_ForwardButton) + m_ForwardButton->SetEnabled(canGoForward); +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h new file mode 100644 index 0000000000..6d5dab8721 --- /dev/null +++ b/src/apps/webpositive/LauncherWindow.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2009 Maxime Simon + * Copyright (C) 2010 Stephan Aßmus + * + * 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 LauncherWindow_h +#define LauncherWindow_h + +#include "WebViewWindow.h" +#include + +class BButton; +class BCheckBox; +class BLayoutItem; +class BMenu; +class BStatusBar; +class BStringView; +class BTextControl; +class WebView; + +enum ToolbarPolicy { + HaveToolbar, + DoNotHaveToolbar +}; + +enum { + NEW_WINDOW = 'nwnd', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc' +}; + +class LauncherWindow : public WebViewWindow { +public: + LauncherWindow(BRect frame, ToolbarPolicy = HaveToolbar); + virtual ~LauncherWindow(); + + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + + // WebViewWindow notification API implementations + virtual void navigationRequested(const BString& url); + virtual void newWindowRequested(const BString& url); + virtual void loadNegociating(const BString& url); + virtual void loadTransfering(const BString& url); + virtual void loadProgress(float progress); + virtual void loadFailed(const BString& url); + virtual void loadFinished(const BString& url); + virtual void titleChanged(const BString& title); + virtual void statusChanged(const BString& status); + virtual void navigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop); + +private: + BMenuBar* m_menuBar; + BButton* m_BackButton; + BButton* m_ForwardButton; + BTextControl* m_url; + BString m_loadedURL; + BStringView* m_statusText; + BStatusBar* m_loadingProgressBar; + BLayoutItem* m_findGroup; + BTextControl* m_findTextControl; + BCheckBox* m_findCaseSensitiveCheckBox; +}; + +#endif // LauncherWindow_h + diff --git a/src/apps/webpositive/LeakTracker.h b/src/apps/webpositive/LeakTracker.h new file mode 100644 index 0000000000..c00b5d1cd8 --- /dev/null +++ b/src/apps/webpositive/LeakTracker.h @@ -0,0 +1,119 @@ +#ifndef LeakTracker_h +#define LeakTracker_h + +// This code is from: +// http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml +// I have modified it some. + +#ifndef NDEBUG + +#if __GNUC__ > 2 + #include + using namespace std; +#endif + +#include +#include + +typedef struct { + int address; + size_t size; + char file[64]; + int line; +} ALLOC_INFO; + +typedef vector AllocList; + +AllocList *allocList; + +void AddTrack(int addr, size_t asize, const char *fname, int lnum) +{ + ALLOC_INFO *info; + + if (!allocList) + allocList = new(AllocList); + + info = new(ALLOC_INFO); + info->address = addr; + strncpy(info->file, fname, 63); + info->line = lnum; + info->size = asize; + allocList->insert(allocList->begin(), info); +}; + +void RemoveTrack(int addr) +{ + AllocList::iterator i; + + if (!allocList) + return; + + for (i = allocList->begin(); i < allocList->end(); i++) { + if ((*i)->address == addr) { + allocList->erase(i); + break; + } + } +}; + +int unfreedCount() +{ + return allocList->size(); +} + +bool nothingUnfreed() +{ + return allocList->empty(); +} + +void OutputDebugString(char *str) +{ + printf(str); +} + +void DumpUnfreed() +{ + AllocList::iterator i; + int totalSize = 0; + char buf[1024]; + + if (!allocList) + return; + + for (i = allocList->begin(); i < allocList->end(); i++) { + sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n", + (*i)->file, (*i)->line, (*i)->address, (int)(*i)->size); + OutputDebugString(buf); + totalSize += (*i)->size; + } + sprintf(buf, "-----------------------------------------------------------\n"); + OutputDebugString(buf); + sprintf(buf, "Total Unfreed: %d bytes\n", totalSize); + OutputDebugString(buf); +}; + +inline void *operator new(size_t size, const char *file, int line) +{ + void *ptr = (void *)malloc(size); + AddTrack((int)ptr, size, file, line); + return(ptr); +}; + +inline void operator delete(void *p) throw() +{ + RemoveTrack((int)p); + free(p); +}; + +#define DEBUG_NEW new(__FILE__, __LINE__) + +#else +#define DEBUG_NEW new +#endif + + +#define new DEBUG_NEW + + +#endif // LeakTracker_h + From d04f705dfcd06a671fb796f8e1a3a7eef9b5f75b Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 12:29:04 +0000 Subject: [PATCH 002/293] Introduced API for setting the caching policy in WebProcess, and used it LauncherApp. The values/code come straight from the GTK port. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@47 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 74b8d84fca..fab6e75589 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -84,6 +84,7 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { WebProcess::initializeOnce(); + WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; From c08684de2a6d9c5358fac5e93dc8a0081ce649b5 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 17:43:55 +0000 Subject: [PATCH 003/293] Removed no longer needed and supposedly non working LeakTracker. On top of this, WebCore already has it's own LeakTracker enabled in debug builds. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@52 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LeakTracker.h | 119 ----------------------------- 1 file changed, 119 deletions(-) delete mode 100644 src/apps/webpositive/LeakTracker.h diff --git a/src/apps/webpositive/LeakTracker.h b/src/apps/webpositive/LeakTracker.h deleted file mode 100644 index c00b5d1cd8..0000000000 --- a/src/apps/webpositive/LeakTracker.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef LeakTracker_h -#define LeakTracker_h - -// This code is from: -// http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml -// I have modified it some. - -#ifndef NDEBUG - -#if __GNUC__ > 2 - #include - using namespace std; -#endif - -#include -#include - -typedef struct { - int address; - size_t size; - char file[64]; - int line; -} ALLOC_INFO; - -typedef vector AllocList; - -AllocList *allocList; - -void AddTrack(int addr, size_t asize, const char *fname, int lnum) -{ - ALLOC_INFO *info; - - if (!allocList) - allocList = new(AllocList); - - info = new(ALLOC_INFO); - info->address = addr; - strncpy(info->file, fname, 63); - info->line = lnum; - info->size = asize; - allocList->insert(allocList->begin(), info); -}; - -void RemoveTrack(int addr) -{ - AllocList::iterator i; - - if (!allocList) - return; - - for (i = allocList->begin(); i < allocList->end(); i++) { - if ((*i)->address == addr) { - allocList->erase(i); - break; - } - } -}; - -int unfreedCount() -{ - return allocList->size(); -} - -bool nothingUnfreed() -{ - return allocList->empty(); -} - -void OutputDebugString(char *str) -{ - printf(str); -} - -void DumpUnfreed() -{ - AllocList::iterator i; - int totalSize = 0; - char buf[1024]; - - if (!allocList) - return; - - for (i = allocList->begin(); i < allocList->end(); i++) { - sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n", - (*i)->file, (*i)->line, (*i)->address, (int)(*i)->size); - OutputDebugString(buf); - totalSize += (*i)->size; - } - sprintf(buf, "-----------------------------------------------------------\n"); - OutputDebugString(buf); - sprintf(buf, "Total Unfreed: %d bytes\n", totalSize); - OutputDebugString(buf); -}; - -inline void *operator new(size_t size, const char *file, int line) -{ - void *ptr = (void *)malloc(size); - AddTrack((int)ptr, size, file, line); - return(ptr); -}; - -inline void operator delete(void *p) throw() -{ - RemoveTrack((int)p); - free(p); -}; - -#define DEBUG_NEW new(__FILE__, __LINE__) - -#else -#define DEBUG_NEW new -#endif - - -#define new DEBUG_NEW - - -#endif // LeakTracker_h - From 4b059d47cd6434ee931e315b9f7698fb532ca42a Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 21:16:25 +0000 Subject: [PATCH 004/293] First basic GUI download progress display... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@54 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 69 ++++++++++++++++++++++++- src/apps/webpositive/DownloadWindow.h | 5 ++ src/apps/webpositive/LauncherApp.cpp | 10 +++- src/apps/webpositive/LauncherApp.h | 3 ++ src/apps/webpositive/LauncherWindow.cpp | 6 ++- src/apps/webpositive/LauncherWindow.h | 3 +- 6 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b27acf86a9..d6b932d6a5 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -28,6 +28,8 @@ #include "config.h" #include "DownloadWindow.h" +#include "WebDownload.h" +#include "WebProcess.h" #include #include #include @@ -35,7 +37,7 @@ #include #include #include - +#include #include DownloadWindow::DownloadWindow(BRect frame) @@ -43,6 +45,7 @@ DownloadWindow::DownloadWindow(BRect frame) B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { + SetLayout(new BGroupLayout(B_VERTICAL)); Minimize(true); Show(); } @@ -54,6 +57,18 @@ DownloadWindow::~DownloadWindow() void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { + case DOWNLOAD_ADDED: { + WebDownload* download; + if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) + downloadStarted(download); + break; + } + case DOWNLOAD_REMOVED: { + WebDownload* download; + if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) + downloadFinished(download); + break; + } default: BWindow::MessageReceived(message); break; @@ -66,3 +81,55 @@ bool DownloadWindow::QuitRequested() Minimize(true); return false; } + +class DownloadProgressView : public BGroupView { +public: + DownloadProgressView(WebDownload* download) + : BGroupView(B_HORIZONTAL) + , m_download(download) + , m_expectedSize(download->expectedSize()) + { + GroupLayout()->SetInsets(5, 5, 5, 5); + m_statusBar = new BStatusBar("download progress", download->filename().String()); + m_statusBar->SetMaxValue(100); + AddChild(m_statusBar); + } + + virtual void AttachedToWindow() + { + m_download->setProgressListener(BMessenger(this)); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case WebDownload::DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + m_statusBar->SetTo(progress); + break; + } + default: + BGroupView::MessageReceived(message); + } + } + + WebDownload* download() const + { + return m_download; + } + +private: + BStatusBar* m_statusBar; + WebDownload* m_download; + off_t m_expectedSize; +}; + +void DownloadWindow::downloadStarted(WebDownload* download) +{ + AddChild(new DownloadProgressView(download)); +} + +void DownloadWindow::downloadFinished(WebDownload* download) +{ +} diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index d263ddf387..dc652f7442 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -30,6 +30,8 @@ #include +class WebDownload; + class DownloadWindow : public BWindow { public: DownloadWindow(BRect frame); @@ -38,6 +40,9 @@ public: virtual void MessageReceived(BMessage*); virtual bool QuitRequested(); + void downloadStarted(WebDownload* download); + void downloadFinished(WebDownload* download); + private: }; diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index fab6e75589..403e750055 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "LauncherApp.h" +#include "DownloadWindow.h" #include "FrameView.h" #include "GraphicsContext.h" #include "LauncherWindow.h" @@ -56,6 +57,7 @@ LauncherApp::LauncherApp() , m_lastWindowFrame(100, 100, 700, 750) , m_launchRefsMessage(0) , m_initialized(false) + , m_downloadWindow(0) { } @@ -86,6 +88,8 @@ void LauncherApp::ReadyToRun() WebProcess::initializeOnce(); WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + m_downloadWindow = new DownloadWindow(BRect(100, 100, 300, 250)); + BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; if (openSettingsFile(settingsFile, B_READ_ONLY)) { @@ -102,7 +106,8 @@ void LauncherApp::ReadyToRun() delete m_launchRefsMessage; m_launchRefsMessage = 0; } else { - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, + BMessenger(m_downloadWindow)); window->Show(); } } @@ -232,7 +237,8 @@ void LauncherApp::newWindow(const BString& url) if (!BScreen().Frame().Contains(m_lastWindowFrame)) m_lastWindowFrame.OffsetTo(50, 50); - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, + BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) window->webView()->loadRequest(url.String()); diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 8afdfc4192..f7efb72dcb 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -32,6 +32,7 @@ #include class BFile; +class DownloadWindow; class LauncherWindow; class LauncherApp : public BApplication { @@ -54,6 +55,8 @@ private: BRect m_lastWindowFrame; BMessage* m_launchRefsMessage; bool m_initialized; + + DownloadWindow* m_downloadWindow; }; extern const char* kApplicationSignature; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 2407f34b45..0a171db2bd 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "LauncherWindow.h" +#include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" @@ -75,7 +76,8 @@ static BLayoutItem* layoutItemFor(BView* view) return layout->ItemAt(index); } -LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) +LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy toolbarPolicy) : WebViewWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) @@ -187,6 +189,8 @@ LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) ); } + webView()->webProcess()->setDownloadListener(downloadListener); + m_findGroup->SetVisible(false); AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 6d5dab8721..46fde08bac 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -55,7 +55,8 @@ enum { class LauncherWindow : public WebViewWindow { public: - LauncherWindow(BRect frame, ToolbarPolicy = HaveToolbar); + LauncherWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy = HaveToolbar); virtual ~LauncherWindow(); virtual void MessageReceived(BMessage* message); From 7a40c9757e509a9e04d288ca40872c0efdcc8538 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 00:29:06 +0000 Subject: [PATCH 005/293] Make the Download Window accessible from every window. Bring it to the workspace that the window is on that send the request to show it. Remember the size and if it was showing across sessions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@56 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- src/apps/webpositive/DownloadWindow.h | 2 +- src/apps/webpositive/LauncherApp.cpp | 27 +++++++++++++++++++++---- src/apps/webpositive/LauncherWindow.cpp | 7 +++++++ src/apps/webpositive/LauncherWindow.h | 3 ++- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index d6b932d6a5..a90b919fd7 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -40,13 +40,14 @@ #include #include -DownloadWindow::DownloadWindow(BRect frame) +DownloadWindow::DownloadWindow(BRect frame, bool visible) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); - Minimize(true); + if (!visible) + Minimize(true); Show(); } diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index dc652f7442..66e88b2940 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,7 +34,7 @@ class WebDownload; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame); + DownloadWindow(BRect frame, bool visible); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage*); diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 403e750055..84a338ff07 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -36,14 +36,13 @@ #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" - #include +#include #include #include #include #include #include - #include extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; @@ -88,17 +87,21 @@ void LauncherApp::ReadyToRun() WebProcess::initializeOnce(); WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); - m_downloadWindow = new DownloadWindow(BRect(100, 100, 300, 250)); - BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; + BRect downloadWindowFrame(100, 100, 300, 250); + bool showDownloads = false; if (openSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); settingsArchive.FindRect("window frame", &windowFrameFromSettings); + settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); + settingsArchive.FindBool("show downloads", &showDownloads); } m_lastWindowFrame = windowFrameFromSettings; + m_downloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + m_initialized = true; if (m_launchRefsMessage) { @@ -165,6 +168,17 @@ void LauncherApp::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; + case SHOW_DOWNLOAD_WINDOW: { + BAutolock _(m_downloadWindow); + uint32 workspaces; + if (message->FindUInt32("workspaces", &workspaces) == B_OK) + m_downloadWindow->SetWorkspaces(workspaces); + if (m_downloadWindow->IsMinimized()) + m_downloadWindow->Minimize(false); + else + m_downloadWindow->Activate(); + } + default: BApplication::MessageReceived(message); break; @@ -215,6 +229,11 @@ bool LauncherApp::QuitRequested() if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; settingsArchive.AddRect("window frame", m_lastWindowFrame); + if (m_downloadWindow->Lock()) { + settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); + settingsArchive.AddBool("show downloads", !m_downloadWindow->IsMinimized()); + m_downloadWindow->Unlock(); + } settingsArchive.Flatten(&settingsFile); } diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 0a171db2bd..bc9c3970c4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -93,6 +93,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, newItem->SetTarget(be_app); menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); @@ -252,6 +254,11 @@ void LauncherWindow::MessageReceived(BMessage* message) m_findGroup->SetVisible(false); break; + case SHOW_DOWNLOAD_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; + default: WebViewWindow::MessageReceived(message); break; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 46fde08bac..0760fc4280 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -50,7 +50,8 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc' + WINDOW_CLOSED = 'wndc', + SHOW_DOWNLOAD_WINDOW = 'sdwd' }; class LauncherWindow : public WebViewWindow { From dd275f312a4c3579e3f2e8a20eecf8607ea655f5 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 01:31:54 +0000 Subject: [PATCH 006/293] More work on the download window GUI. The scroll view is broken, downloads are not persistent. Resolved TODO in WebProcess about race condition when dispatching download notifications. Just block until there is a reply. WebDownload pointers are just used for extracting information at init time, and then later only as cookie to match view and download. Although as soon as we want to cancel downloads, refcounting may become necessary again. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@57 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 72 ++++++++++++++++++++++++- src/apps/webpositive/DownloadWindow.h | 6 +++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index a90b919fd7..b1ad727782 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,22 +30,56 @@ #include "WebDownload.h" #include "WebProcess.h" +#include #include #include #include #include #include +#include #include #include #include #include +enum { + REMOVE_FINISHED_DOWNLOADS = 'rmfd' +}; + DownloadWindow::DownloadWindow(BRect frame, bool visible) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); + + BGroupView* downloadsGroupView = new BGroupView(B_VERTICAL); + downloadsGroupView->SetViewColor(245, 245, 245); + m_downloadViewsLayout = downloadsGroupView->GroupLayout(); + + BMenuBar* menuBar = new BMenuBar("Menu bar"); + BMenu* menu = new BMenu("Window"); + menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); + menuBar->AddItem(menu); + + BScrollView* scrollView = new BScrollView("Downloads scroll view", + downloadsGroupView, 0, false, true, B_NO_BORDER); + + m_removeFinishedButton = new BButton("Remove finished", + new BMessage(REMOVE_FINISHED_DOWNLOADS)); + m_removeFinishedButton->SetEnabled(false); + + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(menuBar) + .Add(scrollView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .AddGlue() + .Add(m_removeFinishedButton) + .SetInsets(5, 5, 5, 5) + ) + ); + if (!visible) Minimize(true); Show(); @@ -70,6 +104,9 @@ void DownloadWindow::MessageReceived(BMessage* message) downloadFinished(download); break; } + case REMOVE_FINISHED_DOWNLOADS: + removeFinishedDownloads(); + break; default: BWindow::MessageReceived(message); break; @@ -90,6 +127,7 @@ public: , m_download(download) , m_expectedSize(download->expectedSize()) { + SetViewColor(245, 245, 245); GroupLayout()->SetInsets(5, 5, 5, 5); m_statusBar = new BStatusBar("download progress", download->filename().String()); m_statusBar->SetMaxValue(100); @@ -120,6 +158,11 @@ public: return m_download; } + void downloadFinished() + { + m_download = NULL; + } + private: BStatusBar* m_statusBar; WebDownload* m_download; @@ -128,9 +171,36 @@ private: void DownloadWindow::downloadStarted(WebDownload* download) { - AddChild(new DownloadProgressView(download)); + m_downloadViewsLayout->AddView(new DownloadProgressView(download)); } void DownloadWindow::downloadFinished(WebDownload* download) { + int32 finishedCount = 0; + for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (view->download() == download) { + view->downloadFinished(); + finishedCount++; + } else if (!view->download()) + finishedCount++; + } + m_removeFinishedButton->SetEnabled(finishedCount > 0); +} + +void DownloadWindow::removeFinishedDownloads() +{ + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (!view->download()) { + view->RemoveSelf(); + delete view; + } + } + m_removeFinishedButton->SetEnabled(false); } diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 66e88b2940..bd370adb17 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -30,6 +30,8 @@ #include +class BButton; +class BGroupLayout; class WebDownload; class DownloadWindow : public BWindow { @@ -40,10 +42,14 @@ public: virtual void MessageReceived(BMessage*); virtual bool QuitRequested(); +private: void downloadStarted(WebDownload* download); void downloadFinished(WebDownload* download); + void removeFinishedDownloads(); private: + BGroupLayout* m_downloadViewsLayout; + BButton* m_removeFinishedButton; }; #endif // DownloadWindow_h From a8d8342dfa61a46c9066df6a7212d641ab71c28c Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 12:51:58 +0000 Subject: [PATCH 007/293] * DownloadWindow is now very usable. * Fixed the scroll view look and behavior. * Downloads are persistent. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@59 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 399 ++++++++++++++++++++---- src/apps/webpositive/DownloadWindow.h | 4 + 2 files changed, 348 insertions(+), 55 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b1ad727782..0b238ff62c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,12 +30,18 @@ #include "WebDownload.h" #include "WebProcess.h" +#include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -43,7 +49,278 @@ #include enum { - REMOVE_FINISHED_DOWNLOADS = 'rmfd' + REMOVE_FINISHED_DOWNLOADS = 'rmfd', + OPEN_DOWNLOAD = 'opdn', + REMOVE_DOWNLOAD = 'rmdn', + SAVE_SETTINGS = 'svst' +}; + +class IconView : public BView { +public: + IconView(const BEntry& entry) + : BView("Download icon", B_WILL_DRAW) + , m_iconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&m_iconBitmap, B_LARGE_ICON); + SetDrawingMode(B_OP_OVER); + } + + IconView(BMessage* archive) + : BView("Download icon", B_WILL_DRAW) + , m_iconBitmap(archive) + { + SetDrawingMode(B_OP_OVER); + } + + status_t saveSettings(BMessage* archive) + { + return m_iconBitmap.Archive(archive); + } + + virtual void AttachedToWindow() + { + SetViewColor(Parent()->ViewColor()); + } + + virtual void Draw(BRect updateRect) + { + DrawBitmapAsync(&m_iconBitmap); + } + + virtual BSize MinSize() + { + return BSize(m_iconBitmap.Bounds().Width(), m_iconBitmap.Bounds().Height()); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual BSize MaxSize() + { + return MinSize(); + } + +private: + BBitmap m_iconBitmap; +}; + +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); + } +}; + +class DownloadProgressView : public BGridView { +public: + DownloadProgressView(WebDownload* download) + : BGridView(8, 3) + , m_download(download) + , m_path(download->path()) + , m_expectedSize(download->expectedSize()) + { + } + + DownloadProgressView(const BMessage* archive) + : BGridView(8, 3) + , m_download(NULL) + , m_path() + , m_expectedSize(0) + { + const char* path; + if (archive->FindString("path", &path) == B_OK) + m_path.SetTo(path); + } + + bool init(BMessage* archive = NULL) + { + BEntry entry(m_path.Path()); + if (!entry.Exists() && !archive) + return false; + + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + + BGridLayout* layout = GridLayout(); + m_statusBar = new BStatusBar("download progress", m_path.Leaf()); + m_statusBar->SetMaxValue(100); + if (archive) { + float value; + if (archive->FindFloat("value", &value) == B_OK) + m_statusBar->SetTo(value); + } + m_statusBar->SetBarHeight(12); + + if (entry.Exists()) + m_iconView = new IconView(entry); + else + m_iconView = new IconView(archive); + + m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + m_button1->SetEnabled(m_download == NULL); + m_button2->SetEnabled(m_download == NULL); + + layout->SetInsets(8, 5, 5, 6); + layout->AddView(m_iconView, 0, 0, 1, 2); + layout->AddView(m_statusBar, 1, 0, 1, 2); + layout->AddView(m_button1, 2, 0); + layout->AddView(m_button2, 2, 1); + + return true; + } + + status_t saveSettings(BMessage* archive) + { + if (!archive) + return B_BAD_VALUE; + status_t ret = archive->AddString("path", m_path.Path()); + if (ret == B_OK) + ret = archive->AddFloat("value", m_statusBar->CurrentValue()); + if (ret == B_OK) + ret = m_iconView->saveSettings(archive); + return ret; + } + + virtual void AttachedToWindow() + { + if (m_download) + m_download->setProgressListener(BMessenger(this)); + m_button1->SetTarget(this); + m_button2->SetTarget(this); + } + + virtual void AllAttached() + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(245, 245, 245); + SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); + } + + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + bounds.bottom--; + FillRect(bounds, B_SOLID_LOW); + bounds.bottom++; + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case WebDownload::DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + m_statusBar->SetTo(progress); + break; + } + case OPEN_DOWNLOAD: { + // TODO: In case of executable files, ask the user first! + entry_ref ref; + status_t status = get_ref_for_path(m_path.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 REMOVE_DOWNLOAD: { + Window()->PostMessage(SAVE_SETTINGS); + RemoveSelf(); + delete this; + // TOAST! + return; + } + default: + BGridView::MessageReceived(message); + } + } + + WebDownload* download() const + { + return m_download; + } + + void downloadFinished() + { + m_download = NULL; + m_button1->SetEnabled(true); + m_button2->SetEnabled(true); + } + +private: + IconView* m_iconView; + BStatusBar* m_statusBar; + SmallButton* m_button1; + SmallButton* m_button2; + WebDownload* m_download; + BPath m_path; + off_t m_expectedSize; +}; + +class DownloadsContainerView : public BGroupView { +public: + DownloadsContainerView() + : BGroupView(B_VERTICAL) + { + SetViewColor(245, 245, 245); + AddChild(BSpaceLayoutItem::CreateGlue()); + } + + virtual BSize MinSize() + { + BSize minSize = BGroupView::MinSize(); + return BSize(minSize.width, 80); + } + +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); + } }; DownloadWindow::DownloadWindow(BRect frame, bool visible) @@ -53,8 +330,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) { SetLayout(new BGroupLayout(B_VERTICAL)); - BGroupView* downloadsGroupView = new BGroupView(B_VERTICAL); - downloadsGroupView->SetViewColor(245, 245, 245); + DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); m_downloadViewsLayout = downloadsGroupView->GroupLayout(); BMenuBar* menuBar = new BMenuBar("Menu bar"); @@ -62,8 +338,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); menuBar->AddItem(menu); - BScrollView* scrollView = new BScrollView("Downloads scroll view", - downloadsGroupView, 0, false, true, B_NO_BORDER); + BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); m_removeFinishedButton = new BButton("Remove finished", new BMessage(REMOVE_FINISHED_DOWNLOADS)); @@ -80,6 +355,10 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) ) ); + loadSettings(); + // Small trick to get the correct enabled status of the Remove finished button + downloadFinished(NULL); + if (!visible) Minimize(true); Show(); @@ -87,6 +366,8 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) DownloadWindow::~DownloadWindow() { + // Only necessary to save the current progress of unfinished downloads: + saveSettings(); } void DownloadWindow::MessageReceived(BMessage* message) @@ -107,6 +388,9 @@ void DownloadWindow::MessageReceived(BMessage* message) case REMOVE_FINISHED_DOWNLOADS: removeFinishedDownloads(); break; + case SAVE_SETTINGS: + saveSettings(); + break; default: BWindow::MessageReceived(message); break; @@ -120,58 +404,13 @@ bool DownloadWindow::QuitRequested() return false; } -class DownloadProgressView : public BGroupView { -public: - DownloadProgressView(WebDownload* download) - : BGroupView(B_HORIZONTAL) - , m_download(download) - , m_expectedSize(download->expectedSize()) - { - SetViewColor(245, 245, 245); - GroupLayout()->SetInsets(5, 5, 5, 5); - m_statusBar = new BStatusBar("download progress", download->filename().String()); - m_statusBar->SetMaxValue(100); - AddChild(m_statusBar); - } - - virtual void AttachedToWindow() - { - m_download->setProgressListener(BMessenger(this)); - } - - virtual void MessageReceived(BMessage* message) - { - switch (message->what) { - case WebDownload::DOWNLOAD_PROGRESS: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - m_statusBar->SetTo(progress); - break; - } - default: - BGroupView::MessageReceived(message); - } - } - - WebDownload* download() const - { - return m_download; - } - - void downloadFinished() - { - m_download = NULL; - } - -private: - BStatusBar* m_statusBar; - WebDownload* m_download; - off_t m_expectedSize; -}; - void DownloadWindow::downloadStarted(WebDownload* download) { - m_downloadViewsLayout->AddView(new DownloadProgressView(download)); + DownloadProgressView* view = new DownloadProgressView(download); + if (!view->init()) + return; + m_downloadViewsLayout->AddView(0, view); + saveSettings(); } void DownloadWindow::downloadFinished(WebDownload* download) @@ -188,6 +427,8 @@ void DownloadWindow::downloadFinished(WebDownload* download) finishedCount++; } m_removeFinishedButton->SetEnabled(finishedCount > 0); + if (download) + saveSettings(); } void DownloadWindow::removeFinishedDownloads() @@ -203,4 +444,52 @@ void DownloadWindow::removeFinishedDownloads() } } m_removeFinishedButton->SetEnabled(false); + saveSettings(); } + +void DownloadWindow::saveSettings() +{ + BFile file; + if (!openSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) + return; + BMessage message; + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(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; + m_downloadViewsLayout->AddView(0, view); + } +} + +bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher_Downloads") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + + diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index bd370adb17..e03fce4a3e 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -31,6 +31,7 @@ #include class BButton; +class BFile; class BGroupLayout; class WebDownload; @@ -46,6 +47,9 @@ private: void downloadStarted(WebDownload* download); void downloadFinished(WebDownload* download); void removeFinishedDownloads(); + void saveSettings(); + void loadSettings(); + bool openSettingsFile(BFile& file, uint32 mode); private: BGroupLayout* m_downloadViewsLayout; From 8260b39fbc6e19008ceea627cc87bf69a38f0045 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 13:17:45 +0000 Subject: [PATCH 008/293] * Now stores the URL of downloads in the DownloadProgressView and in the settings, so that we can eventually restart downloads. * Checks if a downloaded file already has a previous download and replaces it. (Actually, this should take the path into account, not only URL.) * Stores the URL as "META:url" attribute, as the good old NetPositive did. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@60 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0b238ff62c..0511ff194d 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -126,6 +126,7 @@ public: DownloadProgressView(WebDownload* download) : BGridView(8, 3) , m_download(download) + , m_url(download->url()) , m_path(download->path()) , m_expectedSize(download->expectedSize()) { @@ -134,12 +135,15 @@ public: DownloadProgressView(const BMessage* archive) : BGridView(8, 3) , m_download(NULL) + , m_url() , m_path() , m_expectedSize(0) { - const char* path; - if (archive->FindString("path", &path) == B_OK) - m_path.SetTo(path); + const char* string; + if (archive->FindString("path", &string) == B_OK) + m_path.SetTo(string); + if (archive->FindString("url", &string) == B_OK) + m_url = string; } bool init(BMessage* archive = NULL) @@ -185,6 +189,8 @@ public: if (!archive) return B_BAD_VALUE; status_t ret = archive->AddString("path", m_path.Path()); + if (ret == B_OK) + ret = archive->AddString("url", m_url.String()); if (ret == B_OK) ret = archive->AddFloat("value", m_statusBar->CurrentValue()); if (ret == B_OK) @@ -255,6 +261,11 @@ public: return m_download; } + const BString& url() const + { + return m_url; + } + void downloadFinished() { m_download = NULL; @@ -268,6 +279,7 @@ private: SmallButton* m_button1; SmallButton* m_button2; WebDownload* m_download; + BString m_url; BPath m_path; off_t m_expectedSize; }; @@ -406,10 +418,24 @@ bool DownloadWindow::QuitRequested() void DownloadWindow::downloadStarted(WebDownload* download) { + int32 finishedCount = 0; + int32 index = 0; + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (view->url() == download->url()) { + index = i; + view->RemoveSelf(); + delete view; + } + } + m_removeFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); if (!view->init()) return; - m_downloadViewsLayout->AddView(0, view); + m_downloadViewsLayout->AddView(index, view); saveSettings(); } From aab72d7ea63f8951f66a733558a1fe568255a5df Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 13:42:52 +0000 Subject: [PATCH 009/293] * Use hiding instead of minimizing for the Download window. * Auto-show and auto-move-to-current-workspace when a download starts. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@61 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 12 ++++++++---- src/apps/webpositive/LauncherApp.cpp | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0511ff194d..ea0492b402 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -347,7 +347,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) BMenuBar* menuBar = new BMenuBar("Menu bar"); BMenu* menu = new BMenu("Window"); - menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); @@ -372,7 +372,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) downloadFinished(NULL); if (!visible) - Minimize(true); + Hide(); Show(); } @@ -411,8 +411,8 @@ void DownloadWindow::MessageReceived(BMessage* message) bool DownloadWindow::QuitRequested() { - if (!IsMinimized()) - Minimize(true); + if (!IsHidden()) + Hide(); return false; } @@ -437,6 +437,10 @@ void DownloadWindow::downloadStarted(WebDownload* download) return; m_downloadViewsLayout->AddView(index, view); saveSettings(); + + SetWorkspaces(B_CURRENT_WORKSPACE); + if (IsHidden()) + Show(); } void DownloadWindow::downloadFinished(WebDownload* download) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 84a338ff07..44baaf0210 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -173,8 +173,8 @@ void LauncherApp::MessageReceived(BMessage* message) uint32 workspaces; if (message->FindUInt32("workspaces", &workspaces) == B_OK) m_downloadWindow->SetWorkspaces(workspaces); - if (m_downloadWindow->IsMinimized()) - m_downloadWindow->Minimize(false); + if (m_downloadWindow->IsHidden()) + m_downloadWindow->Show(); else m_downloadWindow->Activate(); } @@ -231,7 +231,7 @@ bool LauncherApp::QuitRequested() settingsArchive.AddRect("window frame", m_lastWindowFrame); if (m_downloadWindow->Lock()) { settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !m_downloadWindow->IsMinimized()); + settingsArchive.AddBool("show downloads", !m_downloadWindow->IsHidden()); m_downloadWindow->Unlock(); } settingsArchive.Flatten(&settingsFile); From 5eb61e485689dfd540b2ca4fbfe36809c4bcc6c3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 14 Feb 2010 20:31:05 +0000 Subject: [PATCH 010/293] Added AuthenticationPanel implementation. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@70 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 190 +++++++++++++++++++ src/apps/webpositive/AuthenticationPanel.h | 65 +++++++ src/apps/webpositive/LauncherApp.cpp | 2 + src/apps/webpositive/LauncherWindow.cpp | 24 ++- 4 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/apps/webpositive/AuthenticationPanel.cpp create mode 100644 src/apps/webpositive/AuthenticationPanel.h diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp new file mode 100644 index 0000000000..b6ddb3bd3f --- /dev/null +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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_remberCredentialsCheckBox(new BCheckBox("remember", "Rember this username and password", 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& realm, + const BString& method, const BString& previousUser, const BString& previousPass, + bool previousRememberCredentials, bool badPassword, + BString& user, BString& pass, bool* rememberCredentials) +{ + // Configure panel and layout controls. + BString infoText("Enter login information for: "); + infoText << realm << "\n\n"; + infoText << "Authentication method: "; + infoText << method; + + 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_remberCredentialsCheckBox->SetValue(previousRememberCredentials); + + // create layout + SetLayout(new BGroupLayout(B_VERTICAL)); + float spacing = be_control_look->DefaultItemSpacing(); + AddChild(BGroupLayoutBuilder(B_VERTICAL) + // TODO: Add text view here explaining realm and method... + .Add(BGridLayoutBuilder(0, spacing) + .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 0) + .Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 0) + .Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 1) + .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 0, 2) + .Add(m_hidePasswordCheckBox, 1, 2) + .Add(m_remberCredentialsCheckBox, 0, 3, 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) + ) + ); + + SetDefaultButton(m_okButton); + 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 + // TODO: When called from other window threads, this should periodically + // call UpdateIfNeeded()... + acquire_sem(m_exitSemaphore); + + // AuthenticationPanel wants to quit. + Lock(); + + user = m_usernameTextControl->Text(); + pass = m_passwordTextControl->Text(); + if (rememberCredentials) + *rememberCredentials = m_remberCredentialsCheckBox->Value() == B_CONTROL_ON; + + bool canceled = m_cancelled; + Quit(); + // AuthenticationPanel object is TOAST here. + return !canceled; +} diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h new file mode 100644 index 0000000000..0f8b6ab847 --- /dev/null +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include + +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& realm, const BString& method, + 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_remberCredentialsCheckBox; + BButton* m_okButton; + BButton* m_cancelButton; + + bool m_cancelled; + + sem_id m_exitSemaphore; +}; + +#endif // AuthenticationPanel_h diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 44baaf0210..67792d13d6 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -58,6 +58,8 @@ LauncherApp::LauncherApp() , m_initialized(false) , m_downloadWindow(0) { + // Since we will essentially run the GUI... + set_thread_priority(Thread(), B_DISPLAY_PRIORITY); } LauncherApp::~LauncherApp() diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index bc9c3970c4..08ebb14570 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -31,10 +31,10 @@ #include "config.h" #include "LauncherWindow.h" +#include "AuthenticationPanel.h" #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" - #include #include #include @@ -64,7 +64,9 @@ enum { TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp' + TEXT_FIND_PREVIOUS = 'fndp', + + TEST_AUTHENTICATION_PANEL = 'tapn' }; using namespace WebCore; @@ -199,6 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + AddShortcut('T', B_COMMAND_KEY, new BMessage(TEST_AUTHENTICATION_PANEL)); navigationCapabilitiesChanged(false, false, false); @@ -259,6 +262,23 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; + case TEST_AUTHENTICATION_PANEL: { + BString realm("Realm"); + BString method("Method"); + BString previousUser; + BString previousPass; + bool rememberCredentials = false; + bool badPassword = true; + BString user; + BString pass; + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + bool success = panel->getAuthentication(realm, method, previousUser, + previousPass, rememberCredentials, badPassword, user, pass, + &rememberCredentials); + printf("success: %d\n", success); + break; + } + default: WebViewWindow::MessageReceived(message); break; From a30b7161b85848ac64412901fbbe66ed4fbb1bc2 Mon Sep 17 00:00:00 2001 From: mmlr Date: Mon, 15 Feb 2010 00:30:11 +0000 Subject: [PATCH 011/293] * Handle authentication challenges by sending them off to the WebViewWindow which then invokes the authenticationChallenge() hook. * Implemented that hook in LauncherWindow by means of the AuthenticationPanel. * Removed realm and method arguments to AuthenticationPanel::getAuthentication() and replaced them by a simple "text" that is constructed in the FrameLoaderClient based on the challenge details. It is not yet shown though. * Made a tab -> spaces replace and added myself to the copyrights in some files. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@74 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 9 +- src/apps/webpositive/AuthenticationPanel.h | 8 +- src/apps/webpositive/LauncherWindow.cpp | 207 ++++++++++--------- src/apps/webpositive/LauncherWindow.h | 1 + 4 files changed, 116 insertions(+), 109 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index b6ddb3bd3f..a2c70c2493 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -112,17 +112,12 @@ AuthenticationPanel::MessageReceived(BMessage* message) } } -bool AuthenticationPanel::getAuthentication(const BString& realm, - const BString& method, const BString& previousUser, const BString& previousPass, +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. - BString infoText("Enter login information for: "); - infoText << realm << "\n\n"; - infoText << "Authentication method: "; - infoText << method; - m_usernameTextControl->SetText(previousUser.String()); m_passwordTextControl->TextView()->HideTyping(true); // Ignore the previous password, if it didn't work. diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h index 0f8b6ab847..568f22d1f4 100644 --- a/src/apps/webpositive/AuthenticationPanel.h +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -43,10 +43,10 @@ public: virtual void MessageReceived(BMessage *message); - bool getAuthentication(const BString& realm, const BString& method, - const BString& previousUser, const BString& previousPass, - bool previousRememberCredentials, bool badPassword, BString& user, - BString& pass, bool* rememberCredentials); + 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; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 08ebb14570..872da78b7f 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2007 Ryan Leavengood * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus + * Copyright (C) 2010 Michael Lotz * * All rights reserved. * @@ -57,9 +58,9 @@ enum { GOTO_URL = 'goul', RELOAD = 'reld', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', @@ -73,9 +74,9 @@ using namespace WebCore; static BLayoutItem* layoutItemFor(BView* view) { - BLayout* layout = view->Parent()->GetLayout(); - int32 index = layout->IndexOfView(view); - return layout->ItemAt(index); + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); } LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, @@ -85,30 +86,30 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { if (toolbarPolicy == HaveToolbar) { - // Menu - m_menuBar = new BMenuBar("Main menu"); - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - m_menuBar->AddItem(menu); + // Menu + m_menuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + m_menuBar->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - m_menuBar->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + m_menuBar->AddItem(menu); // Back & Forward m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); @@ -126,16 +127,16 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); m_statusText->SetExplicitMinSize(BSize(150, 16)); - // Prevent the window from growing to fit a long status message... + // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); m_statusText->SetFont(&font, B_FONT_SIZE); - // Loading progress bar - m_loadingProgressBar = new BStatusBar("progress"); - m_loadingProgressBar->SetMaxValue(100); - m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(10); + // Loading progress bar + m_loadingProgressBar = new BStatusBar("progress"); + m_loadingProgressBar->SetMaxValue(100); + m_loadingProgressBar->Hide(); + m_loadingProgressBar->SetBarHeight(10); const float kInsetSpacing = 5; const float kElementSpacing = 7; @@ -158,7 +159,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(m_menuBar) + .Add(m_menuBar) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) @@ -181,8 +182,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_findGroup = layoutItemFor(findGroup); } else { - m_BackButton = 0; - m_ForwardButton = 0; + m_BackButton = 0; + m_ForwardButton = 0; m_url = 0; m_menuBar = 0; m_statusText = 0; @@ -205,7 +206,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, navigationCapabilitiesChanged(false, false, false); - be_app->PostMessage(WINDOW_OPENED); + be_app->PostMessage(WINDOW_OPENED); } LauncherWindow::~LauncherWindow() @@ -262,23 +263,6 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case TEST_AUTHENTICATION_PANEL: { - BString realm("Realm"); - BString method("Method"); - BString previousUser; - BString previousPass; - bool rememberCredentials = false; - bool badPassword = true; - BString user; - BString pass; - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - bool success = panel->getAuthentication(realm, method, previousUser, - previousPass, rememberCredentials, badPassword, user, pass, - &rememberCredentials); - printf("success: %d\n", success); - break; - } - default: WebViewWindow::MessageReceived(message); break; @@ -288,8 +272,8 @@ void LauncherWindow::MessageReceived(BMessage* message) bool LauncherWindow::QuitRequested() { if (WebViewWindow::QuitRequested()) { - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); be_app->PostMessage(&message); return true; } @@ -300,86 +284,113 @@ bool LauncherWindow::QuitRequested() void LauncherWindow::navigationRequested(const BString& url) { - m_loadedURL = url; + m_loadedURL = url; if (m_url) m_url->SetText(url.String()); } void LauncherWindow::newWindowRequested(const BString& url) { - // Always open new windows in the application thread, since - // creating a WebView will try to grab the application lock. - // But our own WebProcess may already try to lock us from within - // the application thread -> dead-lock. - BMessage message(NEW_WINDOW); - message.AddString("url", url); - be_app->PostMessage(&message); + // Always open new windows in the application thread, since + // creating a WebView will try to grab the application lock. + // But our own WebProcess may already try to lock us from within + // the application thread -> dead-lock. + BMessage message(NEW_WINDOW); + message.AddString("url", url); + be_app->PostMessage(&message); } void LauncherWindow::loadNegociating(const BString& url) { - BString status("Requesting: "); - status << url; - statusChanged(status); + BString status("Requesting: "); + status << url; + statusChanged(status); } void LauncherWindow::loadTransfering(const BString& url) { - BString status("Loading: "); - status << url; - statusChanged(status); + BString status("Loading: "); + status << url; + statusChanged(status); } void LauncherWindow::loadProgress(float progress) { - if (m_loadingProgressBar) { - if (progress < 100 && m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Show(); - m_loadingProgressBar->SetTo(progress); - } + if (m_loadingProgressBar) { + if (progress < 100 && m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Show(); + m_loadingProgressBar->SetTo(progress); + } } void LauncherWindow::loadFailed(const BString& url) { - BString status(url); - status << " failed."; - statusChanged(status); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " failed."; + statusChanged(status); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); } void LauncherWindow::loadFinished(const BString& url) { - m_loadedURL = url; - BString status(url); - status << " finished."; - statusChanged(status); + m_loadedURL = url; + BString status(url); + status << " finished."; + statusChanged(status); if (m_url) m_url->SetText(url.String()); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); } void LauncherWindow::titleChanged(const BString& title) { - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); } void LauncherWindow::statusChanged(const BString& statusText) { - if (m_statusText) + if (m_statusText) m_statusText->SetText(statusText.String()); } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop) { - if (m_BackButton) - m_BackButton->SetEnabled(canGoBackward); - if (m_ForwardButton) - m_ForwardButton->SetEnabled(canGoForward); + if (m_BackButton) + m_BackButton->SetEnabled(canGoBackward); + if (m_ForwardButton) + m_ForwardButton->SetEnabled(canGoForward); +} + +void LauncherWindow::authenticationChallenge(BMessage* message) +{ + BString text; + bool rememberCredentials = false; + uint32 failureCount = 0; + BString user; + BString password; + + message->FindString("text", &text); + message->FindString("user", &user); + message->FindString("password", &password); + message->FindUInt32("failureCount", &failureCount); + + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + if (!panel->getAuthentication(text, user, password, rememberCredentials, + failureCount > 0, user, password, &rememberCredentials)) { + message->SendReply((uint32)0); + return; + } + + BMessage reply; + reply.AddString("user", user); + reply.AddString("password", password); + reply.AddBool("rememberCredentials", rememberCredentials); + message->SendReply(&reply); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 0760fc4280..ca4b8391b5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -75,6 +75,7 @@ public: virtual void statusChanged(const BString& status); virtual void navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop); + virtual void authenticationChallenge(BMessage* challenge); private: BMenuBar* m_menuBar; From b067486b740ace89fe237cb802d67213120ce0bb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 10:24:49 +0000 Subject: [PATCH 012/293] Fix loading links from command line args. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@83 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 67792d13d6..019f92852e 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -77,8 +77,14 @@ void LauncherApp::AboutRequested() void LauncherApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { + BEntry entry(argv[i], true); + if (!entry.Exists()) + continue; + BPath path; + if (entry.GetPath(&path) != B_OK) + continue; BMessage message(LOAD_AT_STARTING); - message.AddString("url", argv[i]); + message.AddString("url", path.Path()); message.AddBool("new window", m_initialized || i > 1); PostMessage(&message); } From 04730674fdcf94cf4f5fa066d602b6f9a3267993 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 10:39:24 +0000 Subject: [PATCH 013/293] Support dropping files on LauncherWindows to load them. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@85 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 872da78b7f..7310925007 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -39,11 +39,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -230,6 +232,32 @@ void LauncherWindow::MessageReceived(BMessage* message) webView()->goForward(); break; + case B_SIMPLE_DATA: { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + webView()->loadRequest(path.Path()); + break; + } + case TEXT_SIZE_INCREASE: webView()->increaseTextSize(); break; From 932b58673a54e9ab739f141cb63f154c45a8a1d0 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:23:17 +0000 Subject: [PATCH 014/293] Removed shortcut for testing AuthenticationPanel. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@88 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7310925007..7fb3a366ea 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -68,8 +68,6 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - - TEST_AUTHENTICATION_PANEL = 'tapn' }; using namespace WebCore; @@ -204,7 +202,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('T', B_COMMAND_KEY, new BMessage(TEST_AUTHENTICATION_PANEL)); navigationCapabilitiesChanged(false, false, false); From 56fc5b5b334cbcb45ac2964191eb4069bc70f43c Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:23:47 +0000 Subject: [PATCH 015/293] Fix regression about opening URLs from command line args. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@89 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 019f92852e..df664c7f5a 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -77,14 +77,13 @@ void LauncherApp::AboutRequested() void LauncherApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { + const char* url = argv[i]; BEntry entry(argv[i], true); - if (!entry.Exists()) - continue; BPath path; - if (entry.GetPath(&path) != B_OK) - continue; + if (entry.Exists() && entry.GetPath(&path) == B_OK) + url = path.Path(); BMessage message(LOAD_AT_STARTING); - message.AddString("url", path.Path()); + message.AddString("url", url); message.AddBool("new window", m_initialized || i > 1); PostMessage(&message); } From b2b53e7c19487db73002ccd219920bc07d73feb3 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:25:08 +0000 Subject: [PATCH 016/293] AuthenticationPanel: * Improved wording for persistency checkbox. * Added BTextView for displaying the info text. * Focus password input on second runs with bad password. * Enabled drawing updates for blocking windows. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@90 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 59 +++++++++++++++----- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index a2c70c2493..cebc6e2f88 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -53,7 +53,7 @@ AuthenticationPanel::AuthenticationPanel(BRect 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_remberCredentialsCheckBox(new BCheckBox("remember", "Rember this username and password", NULL)) + , m_remberCredentialsCheckBox(new BCheckBox("remember", "Rember 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) @@ -118,6 +118,15 @@ bool AuthenticationPanel::getAuthentication(const BString& text, 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. @@ -130,15 +139,15 @@ bool AuthenticationPanel::getAuthentication(const BString& text, SetLayout(new BGroupLayout(B_VERTICAL)); float spacing = be_control_look->DefaultItemSpacing(); AddChild(BGroupLayoutBuilder(B_VERTICAL) - // TODO: Add text view here explaining realm and method... .Add(BGridLayoutBuilder(0, spacing) - .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 0) - .Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 0) - .Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 1) - .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 1) - .Add(BSpaceLayoutItem::CreateGlue(), 0, 2) - .Add(m_hidePasswordCheckBox, 1, 2) - .Add(m_remberCredentialsCheckBox, 0, 3, 2) + .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_remberCredentialsCheckBox, 0, 4, 2) .SetInsets(spacing, spacing, spacing, spacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -150,8 +159,14 @@ bool AuthenticationPanel::getAuthentication(const BString& text, ) ); + float textHeight = textView->LineHeight(0) * textView->CountLines(); + textView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); + SetDefaultButton(m_okButton); - m_usernameTextControl->MakeFocus(true); + if (badPassword && previousUser.Length()) + m_passwordTextControl->MakeFocus(true); + else + m_usernameTextControl->MakeFocus(true); if (m_parentWindowFrame.IsValid()) CenterIn(m_parentWindowFrame); @@ -166,9 +181,27 @@ bool AuthenticationPanel::getAuthentication(const BString& text, PostMessage(kMsgJitter); // Block calling thread - // TODO: When called from other window threads, this should periodically - // call UpdateIfNeeded()... - acquire_sem(m_exitSemaphore); + // Get the originating window, if it exists, to let it redraw itself. + BWindow* window = dynamic_cast(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(); From 77d2abe296cba1de16ae16bdaf53300b44efde08 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 14:06:28 +0000 Subject: [PATCH 017/293] First structure of BrowsingHistory. Does nothing, but can in theory save settings. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@91 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 83 ++++++++++++++++++++++++ src/apps/webpositive/BrowsingHistory.h | 51 +++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/apps/webpositive/BrowsingHistory.cpp create mode 100644 src/apps/webpositive/BrowsingHistory.h diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp new file mode 100644 index 0000000000..e70d3c0e03 --- /dev/null +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 "config.h" +#include "BrowsingHistory.h" + +#include +#include +#include +#include +#include +#include + + +BrowsingHistory BrowsingHistory::s_defaultInstance; + +BrowsingHistory::BrowsingHistory() + : BLocker("browsing history") +{ + BFile settingsFile; + if (openSettingsFile(settingsFile, B_READ_ONLY)) { + BMessage settingsArchive; + settingsArchive.Unflatten(&settingsFile); + // TODO: ... + } +} + +BrowsingHistory::~BrowsingHistory() +{ + saveSettings(); +} + +/*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() +{ + return &s_defaultInstance; +} + +// #pragma mark - private + +void BrowsingHistory::saveSettings() +{ + BFile settingsFile; + if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + BMessage settingsArchive; + // TODO: ... + settingsArchive.Flatten(&settingsFile); + } +} + +bool BrowsingHistory::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher_BrowsingHistory") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h new file mode 100644 index 0000000000..82ef0ba04f --- /dev/null +++ b/src/apps/webpositive/BrowsingHistory.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 BrowsingHistory_h +#define BrowsingHistory_h + +#include + +class BFile; + +class BrowsingHistory : public BLocker { +public: + static BrowsingHistory* defaultInstance(); + +private: + BrowsingHistory(); + virtual ~BrowsingHistory(); + + void saveSettings(); + bool openSettingsFile(BFile& file, uint32 mode); + +private: + static BrowsingHistory s_defaultInstance; +}; + +#endif // BrowsingHistory_h + From 4e703b4b2f21ca170a7700241426abfad821bd8e Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 15:58:35 +0000 Subject: [PATCH 018/293] Patch by Rene Gollent, which fixes some typos. Thanks! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@92 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 8 ++++---- src/apps/webpositive/AuthenticationPanel.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index cebc6e2f88..8d81bbb311 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -53,7 +53,7 @@ AuthenticationPanel::AuthenticationPanel(BRect 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_remberCredentialsCheckBox(new BCheckBox("remember", "Rember username and password for this site", NULL)) + , 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) @@ -133,7 +133,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, if (!badPassword) m_passwordTextControl->SetText(previousPass.String()); m_hidePasswordCheckBox->SetValue(B_CONTROL_ON); - m_remberCredentialsCheckBox->SetValue(previousRememberCredentials); + m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials); // create layout SetLayout(new BGroupLayout(B_VERTICAL)); @@ -147,7 +147,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 2) .Add(BSpaceLayoutItem::CreateGlue(), 0, 3) .Add(m_hidePasswordCheckBox, 1, 3) - .Add(m_remberCredentialsCheckBox, 0, 4, 2) + .Add(m_rememberCredentialsCheckBox, 0, 4, 2) .SetInsets(spacing, spacing, spacing, spacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -209,7 +209,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, user = m_usernameTextControl->Text(); pass = m_passwordTextControl->Text(); if (rememberCredentials) - *rememberCredentials = m_remberCredentialsCheckBox->Value() == B_CONTROL_ON; + *rememberCredentials = m_rememberCredentialsCheckBox->Value() == B_CONTROL_ON; bool canceled = m_cancelled; Quit(); diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h index 568f22d1f4..5af9496aad 100644 --- a/src/apps/webpositive/AuthenticationPanel.h +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -53,7 +53,7 @@ private: BTextControl* m_usernameTextControl; BTextControl* m_passwordTextControl; BCheckBox* m_hidePasswordCheckBox; - BCheckBox* m_remberCredentialsCheckBox; + BCheckBox* m_rememberCredentialsCheckBox; BButton* m_okButton; BButton* m_cancelButton; From dad9d4a5a4e0f627fa2b11ff1cac30c8118bf575 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:22:13 +0000 Subject: [PATCH 019/293] Added BDateTime stuff from Haiku, and addd archiving features to these classes. Needs to be put back into Haiku and made public API eventually. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@93 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DateTime.cpp | 1367 +++++++++++++++++++++++++++++ src/apps/webpositive/DateTime.h | 215 +++++ 2 files changed, 1582 insertions(+) create mode 100644 src/apps/webpositive/DateTime.cpp create mode 100644 src/apps/webpositive/DateTime.h diff --git a/src/apps/webpositive/DateTime.cpp b/src/apps/webpositive/DateTime.cpp new file mode 100644 index 0000000000..7818dc36c2 --- /dev/null +++ b/src/apps/webpositive/DateTime.cpp @@ -0,0 +1,1367 @@ +/* + * Copyright 2007-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Julun + * Stephan Aßmus + */ + +#include "DateTime.h" + + +#include +#include + +#include + + +namespace BPrivate { + + +const int32 kSecondsPerMinute = 60; + +const int32 kHoursPerDay = 24; +const int32 kMinutesPerDay = 1440; +const int32 kSecondsPerDay = 86400; +const int32 kMillisecondsPerDay = 86400000; + +const bigtime_t kMicrosecondsPerSecond = 1000000LL; +const bigtime_t kMicrosecondsPerMinute = 60000000LL; +const bigtime_t kMicrosecondsPerHour = 3600000000LL; +const bigtime_t kMicrosecondsPerDay = 86400000000LL; + + +/*! + Constructs a new BTime object. Asked for its time representation, it will + return 0 for Hour(), Minute(), Second() etc. This can represent midnight, + but be aware IsValid() will return false. +*/ +BTime::BTime() + : fMicroseconds(-1) +{ +} + + +/*! + Constructs a BTime object with \c hour \c minute, \c second, \c microsecond. + + \c hour must be between 0 and 23, \c minute and \c second must be between + 0 and 59 and \c microsecond should be in the range of 0 and 999999. If the + specified time is invalid, the time is not set and IsValid() returns false. +*/ +BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) + : fMicroseconds(-1) +{ + _SetTime(hour, minute, second, microsecond); +} + + +/*! + Constructs a new BTime object from the provided BMessage archive. +*/ +BTime::BTime(const BMessage* archive) + : fMicroseconds(-1) +{ + if (archive == NULL) + return; + archive->FindInt64("mircoseconds", &fMicroseconds); +} + + +/*! + Empty destructor. +*/ +BTime::~BTime() +{ +} + + +/*! + Archives the BTime object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BTime::Archive(BMessage* into) const +{ + if (into == NULL) + return B_BAD_VALUE; + return into->AddInt64("mircoseconds", fMicroseconds); +} + + +/*! + Returns true if the time is valid, otherwise false. A valid time can be + BTime(23, 59, 59, 999999) while BTime(24, 00, 01) would be invalid. +*/ +bool +BTime::IsValid() const +{ + return fMicroseconds > -1 && fMicroseconds < kMicrosecondsPerDay; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BTime::IsValid(const BTime& time) const +{ + return time.fMicroseconds > -1 && time.fMicroseconds < kMicrosecondsPerDay; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BTime::IsValid(int32 hour, int32 minute, int32 second, int32 microsecond) const +{ + return BTime(hour, minute, second, microsecond).IsValid(); +} + + +/*! + Returns the current time as reported by the system depending on the given + time_type \c type. +*/ +BTime +BTime::CurrentTime(time_type type) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) { + // gettimeofday failed? + time(&tv.tv_sec); + } + + struct tm result; + struct tm* timeinfo; + if (type == B_GMT_TIME) + timeinfo = gmtime_r(&tv.tv_sec, &result); + else + timeinfo = localtime_r(&tv.tv_sec, &result); + + int32 sec = timeinfo->tm_sec; + return BTime(timeinfo->tm_hour, timeinfo->tm_min, (sec > 59) ? 59 : sec, + tv.tv_usec); +} + + +/*! + Returns a copy of the current BTime object. +*/ +BTime +BTime::Time() const +{ + return *this; +} + + +/*! + This is an overloaded member function, provided for convenience. Set the + current BTime object to the passed BTime \c time object. +*/ +bool +BTime::SetTime(const BTime& time) +{ + fMicroseconds = time.fMicroseconds; + return IsValid(); +} + + +/*! + Set the time to \c hour \c minute, \c second and \c microsecond. + + \c hour must be between 0 and 23, \c minute and \c second must be between + 0 and 59 and \c microsecond should be in the range of 0 and 999999. Returns + true if the time is valid; otherwise false. If the specified time is + invalid, the time is not set and the function returns false. +*/ +bool +BTime::SetTime(int32 hour, int32 minute, int32 second, int32 microsecond) +{ + return _SetTime(hour, minute, second, microsecond); +} + + + +/*! + Adds \c hours to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddHours(int32 hours) +{ + _AddMicroseconds(bigtime_t(hours % kHoursPerDay) * kMicrosecondsPerHour); +} + + +/*! + Adds \c minutes to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMinutes(int32 minutes) +{ + _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) * + kMicrosecondsPerMinute); +} + + +/*! + Adds \c seconds to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddSeconds(int32 seconds) +{ + _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) * + kMicrosecondsPerSecond); +} + + +/*! + Adds \c milliseconds to the current time. If the passed value is negativ it + will become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMilliseconds(int32 milliseconds) +{ + _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) * 1000); +} + + +/*! + Adds \c microseconds to the current time. If the passed value is negativ it + will become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMicroseconds(int32 microseconds) +{ + _AddMicroseconds(microseconds); +} + + +/*! + Returns the hour fragment of the time. +*/ +int32 +BTime::Hour() const +{ + return int32(_Microseconds() / kMicrosecondsPerHour); +} + + +/*! + Returns the minute fragment of the time. +*/ +int32 +BTime::Minute() const +{ + return int32(((_Microseconds() % kMicrosecondsPerHour)) / kMicrosecondsPerMinute); +} + + +/*! + Returns the second fragment of the time. +*/ +int32 +BTime::Second() const +{ + return int32(_Microseconds() / kMicrosecondsPerSecond) % kSecondsPerMinute; +} + + +/*! + Returns the millisecond fragment of the time. +*/ +int32 +BTime::Millisecond() const +{ + + return Microsecond() / 1000; +} + + +/*! + Returns the microsecond fragment of the time. +*/ +int32 +BTime::Microsecond() const +{ + return int32(_Microseconds() % 1000000); +} + + +bigtime_t +BTime::_Microseconds() const +{ + return fMicroseconds == -1 ? 0 : fMicroseconds; +} + + +/*! + Returns the difference between this time and the given BTime \c time based + on the passed diff_type \c type. If \c time is earlier the return value will + be negativ. + + The return value then can be hours, minutes, seconds, milliseconds or + microseconds while its range will always be between -86400000000 and + 86400000000 depending on diff_type \c type. +*/ +bigtime_t +BTime::Difference(const BTime& time, diff_type type) const +{ + bigtime_t diff = time._Microseconds() - _Microseconds(); + switch (type) { + case B_HOURS_DIFF: { + diff /= kMicrosecondsPerHour; + } break; + case B_MINUTES_DIFF: { + diff /= kMicrosecondsPerMinute; + } break; + case B_SECONDS_DIFF: { + diff /= kMicrosecondsPerSecond; + } break; + case B_MILLISECONDS_DIFF: { + diff /= 1000; + } break; + case B_MICROSECONDS_DIFF: + default: break; + } + return diff; +} + + +/*! + Returns true if this time is different from \c time, otherwise false. +*/ +bool +BTime::operator!=(const BTime& time) const +{ + return fMicroseconds != time.fMicroseconds; +} + + +/*! + Returns true if this time is equal to \c time, otherwise false. +*/ +bool +BTime::operator==(const BTime& time) const +{ + return fMicroseconds == time.fMicroseconds; +} + + +/*! + Returns true if this time is earlier than \c time, otherwise false. +*/ +bool +BTime::operator<(const BTime& time) const +{ + return fMicroseconds < time.fMicroseconds; +} + + +/*! + Returns true if this time is earlier than or equal to \c time, otherwise false. +*/ +bool +BTime::operator<=(const BTime& time) const +{ + return fMicroseconds <= time.fMicroseconds; +} + + +/*! + Returns true if this time is later than \c time, otherwise false. +*/ +bool +BTime::operator>(const BTime& time) const +{ + return fMicroseconds > time.fMicroseconds; +} + + +/*! + Returns true if this time is later than or equal to \c time, otherwise false. +*/ +bool +BTime::operator>=(const BTime& time) const +{ + return fMicroseconds >= time.fMicroseconds; +} + + +void +BTime::_AddMicroseconds(bigtime_t microseconds) +{ + bigtime_t count = 0; + if (microseconds < 0) { + count = ((kMicrosecondsPerDay - microseconds) / kMicrosecondsPerDay) * + kMicrosecondsPerDay; + } + fMicroseconds = (_Microseconds() + microseconds + count) % kMicrosecondsPerDay; +} + + +bool +BTime::_SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, + bigtime_t microsecond) +{ + fMicroseconds = hour * kMicrosecondsPerHour + + minute * kMicrosecondsPerMinute + + second * kMicrosecondsPerSecond + + microsecond; + + bool isValid = IsValid(); + if (!isValid) + fMicroseconds = -1; + + return isValid; +} + + +// #pragma mark - BDate + + +/*! + Constructs a new BDate object. IsValid() will return false. +*/ +BDate::BDate() + : fDay(-1), + fYear(0), + fMonth(-1) +{ +} + + +/*! + Constructs a BDate object with \c year \c month and \c day. + + Please note that a date before 1.1.4713 BC, a date with year 0 and a date + between 4.10.1582 and 15.10.1582 are considered invalid. If the specified + date is invalid, the date is not set and IsValid() returns false. Also note + that every passed year will be interpreted as is. + +*/ +BDate::BDate(int32 year, int32 month, int32 day) +{ + _SetDate(year, month, day); +} + + +/*! + Constructs a new BDate object from the provided archive. +*/ +BDate::BDate(const BMessage* archive) + : fDay(-1), + fYear(0), + fMonth(-1) +{ + if (archive == NULL) + return; + archive->FindInt32("day", &fDay); + archive->FindInt32("year", &fYear); + archive->FindInt32("month", &fMonth); +} + + +/*! + Empty destructor. +*/ +BDate::~BDate() +{ +} + + +/*! + Archives the BDate object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BDate::Archive(BMessage* into) const +{ + if (into == NULL) + return B_BAD_VALUE; + status_t ret = into->AddInt32("day", fDay); + if (ret == B_OK) + ret = into->AddInt32("year", fYear); + if (ret == B_OK) + ret = into->AddInt32("month", fMonth); + return ret; +} + + +/*! + Returns true if the date is valid, otherwise false. + + Please note that a date before 1.1.4713 BC, a date with year 0 and a date + between 4.10.1582 and 15.10.1582 are considered invalid. +*/ +bool +BDate::IsValid() const +{ + return IsValid(fYear, fMonth, fDay); +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::IsValid(const BDate& date) const +{ + return IsValid(date.fYear, date.fMonth, date.fDay); +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::IsValid(int32 year, int32 month, int32 day) const +{ + // no year 0 in Julian and nothing before 1.1.4713 BC + if (year == 0 || year < -4713) + return false; + + if (month < 1 || month > 12) + return false; + + if (day < 1 || day > _DaysInMonth(year, month)) + return false; + + // 'missing' days between switch julian - gregorian + if (year == 1582 && month == 10 && day > 4 && day < 15) + return false; + + return true; +} + + +/*! + Returns the current date as reported by the system depending on the given + time_type \c type. +*/ +BDate +BDate::CurrentDate(time_type type) +{ + time_t timer; + struct tm result; + struct tm* timeinfo; + + time(&timer); + + if (type == B_GMT_TIME) + timeinfo = gmtime_r(&timer, &result); + else + timeinfo = localtime_r(&timer, &result); + + return BDate(timeinfo->tm_year + 1900, timeinfo->tm_mon +1, timeinfo->tm_mday); +} + + +/*! + Returns a copy of the current BTime object. +*/ +BDate +BDate::Date() const +{ + return *this; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::SetDate(const BDate& date) +{ + return _SetDate(date.fYear, date.fMonth, date.fDay); +} + + +/*! + Set the date to \c year \c month and \c day. + + Returns true if the date is valid; otherwise false. If the specified date is + invalid, the date is not set and the function returns false. +*/ +bool +BDate::SetDate(int32 year, int32 month, int32 day) +{ + return _SetDate(year, month, day); +} + + +/*! + This function sets the given \c year, \c month and \c day to the + representative values of this date. The pointers can be NULL. If the date is + invalid, the values will be set to -1 for \c month and \c day, the \c year + will be set to 0. +*/ +void +BDate::GetDate(int32* year, int32* month, int32* day) +{ + if (year) + *year = fYear; + + if (month) + *month = fMonth; + + if (day) + *day = fDay; +} + + +/*! + Adds \c days to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c days are not added. +*/ +void +BDate::AddDays(int32 days) +{ + if (IsValid()) + *this = JulianDayToDate(DateToJulianDay() + days); +} + + +/*! + Adds \c years to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c years are not added. + The day/ month combination will be adjusted if it does not exist in the + resulting year, so this function will then return the latest valid date. +*/ +void +BDate::AddYears(int32 years) +{ + if (IsValid()) { + const int32 tmp = fYear; + fYear += years; + + if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0)) + fYear += (years > 0) ? +1 : -1; + + fDay = min_c(fDay, _DaysInMonth(fYear, fMonth)); + } +} + + +/*! + Adds \c months to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c months are not added. + The day/ month combination will be adjusted if it does not exist in the + resulting year, so this function will then return the latest valid date. +*/ +void +BDate::AddMonths(int32 months) +{ + if (IsValid()) { + const int32 tmp = fYear; + fYear += months / 12; + fMonth += months % 12; + + if (fMonth > 12) { + fYear++; + fMonth -= 12; + } else if (fMonth < 1) { + fYear--; + fMonth += 12; + } + + if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0)) + fYear += (months > 0) ? +1 : -1; + + // 'missing' days between switch julian - gregorian + if (fYear == 1582 && fMonth == 10 && fDay > 4 && fDay < 15) + fDay = (months > 0) ? 15 : 4; + + fDay = min_c(fDay, DaysInMonth()); + } +} + + +/*! + Returns the day fragment of the date. The return value will be in the range + of 1 to 31, in case the date is invalid it will be -1. +*/ +int32 +BDate::Day() const +{ + return fDay; +} + + +/*! + Returns the year fragment of the date. If the date is invalid, the function + returns 0. +*/ +int32 +BDate::Year() const +{ + return fYear; +} + + +/*! + Returns the month fragment of the date. The return value will be in the + range of 1 to 12, in case the date is invalid it will be -1. +*/ +int32 +BDate::Month() const +{ + return fMonth; +} + + +/*! + Returns the difference in days between this date and the given BDate \c date. + If \c date is earlier the return value will be negativ. If the calculation + is done with an invalid date, the result is undefined. +*/ +int32 +BDate::Difference(const BDate& date) const +{ + return date.DateToJulianDay() - DateToJulianDay(); +} + + +/*! + Returns the week number of the date, if the date is invalid it will return + B_ERROR. Please note that this function does only work within the Gregorian + calendar, thus a date before 15.10.1582 will return B_ERROR. +*/ +int32 +BDate::WeekNumber() const +{ + /* + This algorithm is taken from: + Frequently Asked Questions about Calendars + Version 2.8 Claus Tøndering 15 December 2005 + + Note: it will work only within the Gregorian Calendar + */ + + if (!IsValid() || fYear < 1582 + || (fYear == 1582 && fMonth < 10) + || (fYear == 1582 && fMonth == 10 && fDay < 15)) + return int32(B_ERROR); + + int32 a; + int32 b; + int32 s; + int32 e; + int32 f; + + if (fMonth > 0 && fMonth < 3) { + a = fYear - 1; + b = (a / 4) - (a / 100) + (a / 400); + int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400); + s = b - c; + e = 0; + f = fDay - 1 + 31 * (fMonth - 1); + } else if (fMonth >= 3 && fMonth <= 12) { + a = fYear; + b = (a / 4) - (a / 100) + (a / 400); + int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400); + s = b - c; + e = s + 1; + f = fDay + ((153 * (fMonth - 3) + 2) / 5) + 58 + s; + } else + return int32(B_ERROR); + + int32 g = (a + b) % 7; + int32 d = (f + g - e) % 7; + int32 n = f + 3 - d; + + int32 weekNumber; + if (n < 0) + weekNumber = 53 - (g -s) / 5; + else if (n > 364 + s) + weekNumber = 1; + else + weekNumber = n / 7 + 1; + + return weekNumber; +} + + +/*! + Returns the day of the week in the range of 1 to 7, while 1 stands for + monday. If the date is invalid, the function will return B_ERROR. +*/ +int32 +BDate::DayOfWeek() const +{ + // http://en.wikipedia.org/wiki/Julian_day#Calculation + return IsValid() ? (DateToJulianDay() % 7) + 1 : int32(B_ERROR); +} + + +/*! + Returns the day of the year in the range of 1 to 365 (366 in leap years). If + the date is invalid, the function will return B_ERROR. +*/ +int32 +BDate::DayOfYear() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return DateToJulianDay() - _DateToJulianDay(fYear, 1, 1) + 1; +} + + +/*! + Returns true if the passed \c year is a leap year, otherwise false. If the + \c year passed is before 4713 BC, the result is undefined. +*/ +bool +BDate::IsLeapYear(int32 year) const +{ + if (year < 1582) { + if (year < 0) + year++; + return (year % 4) == 0; + } + return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); +} + + +/*! + Returns the number of days in the year of the current date. If the date is + valid it will return 365 or 366, otherwise B_ERROR; +*/ +int32 +BDate::DaysInYear() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return IsLeapYear(fYear) ? 366 : 365; +} + + +/*! + Returns the number of days in the month of the current date. If the date is + valid it will return 28 up to 31, otherwise B_ERROR; +*/ +int32 +BDate::DaysInMonth() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return _DaysInMonth(fYear, fMonth); +} + + +/*! + Returns the short day name in case of an valid day, otherwise an empty + string. The passed \c day must be in the range of 1 to 7 while 1 stands for + monday. +*/ +BString +BDate::ShortDayName(int32 day) const +{ + if (day < 1 || day > 7) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_wday = day == 7 ? 0 : day; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%a", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the short month name in case of an valid month, otherwise an empty + string. The passed \c month must be in the range of 1 to 12. +*/ +BString +BDate::ShortMonthName(int32 month) const +{ + if (month < 1 || month > 12) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_mon = month - 1; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%b", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the long day name in case of an valid day, otherwise an empty + string. The passed \c day must be in the range of 1 to 7 while 1 stands for + monday. +*/ +BString +BDate::LongDayName(int32 day) const +{ + if (day < 1 || day > 7) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_wday = day == 7 ? 0 : day; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%A", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the long month name in case of an valid month, otherwise an empty + string. The passed \c month must be in the range of 1 to 12. +*/ +BString +BDate::LongMonthName(int32 month) const +{ + if (month < 1 || month > 12) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_mon = month - 1; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%B", &tm_struct); + + return BString(buffer); +} + + +/*! + Converts the date to Julian day. If your date is invalid, the function will + return B_ERROR. +*/ +int32 +BDate::DateToJulianDay() const +{ + return _DateToJulianDay(fYear, fMonth, fDay); +} + + +/* + Converts the passed \c julianDay to an BDate. If the \c julianDay is negativ, + the function will return an invalid date. Because of the switch from Julian + calendar to Gregorian calendar the 4.10.1582 is followed by the 15.10.1582. +*/ +BDate +BDate::JulianDayToDate(int32 julianDay) +{ + BDate date; + const int32 kGregorianCalendarStart = 2299161; + if (julianDay >= kGregorianCalendarStart) { + // http://en.wikipedia.org/wiki/Julian_day#Gregorian_calendar_from_Julian_day_number + int32 j = julianDay + 32044; + int32 dg = j % 146097; + int32 c = (dg / 36524 + 1) * 3 / 4; + int32 dc = dg - c * 36524; + int32 db = dc % 1461; + int32 a = (db / 365 + 1) * 3 / 4; + int32 da = db - a * 365; + int32 m = (da * 5 + 308) / 153 - 2; + date.fYear = ((j / 146097) * 400 + c * 100 + (dc / 1461) * 4 + a) - 4800 + + (m + 2) / 12; + date.fMonth = (m + 2) % 12 + 1; + date.fDay = int32((da - (m + 4) * 153 / 5 + 122) + 1.5); + } else if (julianDay >= 0) { + // http://en.wikipedia.org/wiki/Julian_day#Calculation + julianDay += 32082; + int32 d = (4 * julianDay + 3) / 1461; + int32 e = julianDay - (1461 * d) / 4; + int32 m = ((5 * e) + 2) / 153; + date.fDay = e - (153 * m + 2) / 5 + 1; + date.fMonth = m + 3 - 12 * (m / 10); + int32 year = d - 4800 + (m / 10); + if (year <= 0) + year--; + date.fYear = year; + } + return date; +} + + +/*! + Returns true if this date is different from \c date, otherwise false. +*/ +bool +BDate::operator!=(const BDate& date) const +{ + return DateToJulianDay() != date.DateToJulianDay(); +} + + +/*! + Returns true if this date is equal to \c date, otherwise false. +*/ +bool +BDate::operator==(const BDate& date) const +{ + return DateToJulianDay() == date.DateToJulianDay(); +} + + +/*! + Returns true if this date is earlier than \c date, otherwise false. +*/ +bool +BDate::operator<(const BDate& date) const +{ + return DateToJulianDay() < date.DateToJulianDay(); +} + + +/*! + Returns true if this date is earlier than or equal to \c date, otherwise false. +*/ +bool +BDate::operator<=(const BDate& date) const +{ + return DateToJulianDay() <= date.DateToJulianDay(); +} + + +/*! + Returns true if this date is later than \c date, otherwise false. +*/ +bool +BDate::operator>(const BDate& date) const +{ + return DateToJulianDay() > date.DateToJulianDay(); +} + + +/*! + Returns true if this date is later than or equal to \c date, otherwise false. +*/ +bool +BDate::operator>=(const BDate& date) const +{ + return DateToJulianDay() >= date.DateToJulianDay(); +} + + +bool +BDate::_SetDate(int32 year, int32 month, int32 day) +{ + fDay = -1; + fYear = 0; + fMonth = -1; + + bool valid = IsValid(year, month, day); + if (valid) { + fDay = day; + fYear = year; + fMonth = month; + } + + return valid; +} + + +int32 +BDate::_DaysInMonth(int32 year, int32 month) const +{ + if (month == 2 && IsLeapYear(year)) + return 29; + + const int32 daysInMonth[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + return daysInMonth[month -1]; +} + + +int32 +BDate::_DateToJulianDay(int32 _year, int32 month, int32 day) const +{ + if (IsValid(_year, month, day)) { + int32 year = _year; + if (year < 0) year++; + + int32 a = (14 - month) / 12; + int32 y = year + 4800 - a; + int32 m = month + (12 * a) - 3; + + // http://en.wikipedia.org/wiki/Julian_day#Calculation + if (year > 1582 + || (year == 1582 && month > 10) + || (year == 1582 && month == 10 && day >= 15)) { + return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - + (y / 100) + (y / 400) - 32045; + } else if (year < 1582 + || (year == 1582 && month < 10) + || (year == 1582 && month == 10 && day <= 4)) { + return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - 32083; + } + } + + // http://en.wikipedia.org/wiki/Gregorian_calendar: + // The last day of the Julian calendar was Thursday October 4, 1582 + // and this was followed by the first day of the Gregorian calendar, + // Friday October 15, 1582 (the cycle of weekdays was not affected). + return int32(B_ERROR); +} + + +// #pragma mark - BDateTime + + +/*! + Constructs a new BDateTime object. IsValid() will return false. +*/ +BDateTime::BDateTime() + : fDate(), + fTime() +{ +} + + +/*! + Constructs a BDateTime object with \c date and \c time. The return value + of IsValid() depends on the validity of the passed objects. +*/ +BDateTime::BDateTime(const BDate& date, const BTime& time) + : fDate(date), + fTime(time) +{ +} + + +/*! + Constructs a new BDateTime object. IsValid() will return false. +*/ +BDateTime::BDateTime(const BMessage* archive) + : fDate(archive), + fTime(archive) +{ +} + + +/*! + Empty destructor. +*/ +BDateTime::~BDateTime() +{ +} + + +/*! + Archives the BDateTime object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BDateTime::Archive(BMessage* into) const +{ + status_t ret = fDate.Archive(into); + if (ret == B_OK) + ret = fTime.Archive(into); + return ret; +} + + +/*! + Returns true if the date time is valid, otherwise false. +*/ +bool +BDateTime::IsValid() const +{ + return fDate.IsValid() && fTime.IsValid(); +} + + +/*! + Returns the current date and time as reported by the system depending on the + given time_type \c type. +*/ +BDateTime +BDateTime::CurrentDateTime(time_type type) +{ + return BDateTime(BDate::CurrentDate(type), BTime::CurrentTime(type)); +} + + +/*! + Sets the current date and time of this object to \c date and \c time. +*/ +void +BDateTime::SetDateTime(const BDate& date, const BTime& time) +{ + fDate = date; + fTime = time; +} + + +/*! + Returns the current date of this object. +*/ +BDate +BDateTime::Date() const +{ + return fDate; +} + + +/*! + Set the current date of this object to \c date. +*/ +void +BDateTime::SetDate(const BDate& date) +{ + fDate = date; +} + + +/*! + Returns the current time of this object. +*/ +BTime +BDateTime::Time() const +{ + return fTime; +} + + +/*! + Sets the current time of this object to \c time. +*/ +void +BDateTime::SetTime(const BTime& time) +{ + fTime = time; +} + + +/*! + Returns the current date and time converted to seconds since + 1.1.1970 - 00:00:00. If the current date is before 1.1.1970 the function + returns -1; +*/ +int32 +BDateTime::Time_t() const +{ + BDate date(1970, 1, 1); + if (date.Difference(fDate) < 0) + return -1; + + tm tm_struct; + + tm_struct.tm_hour = fTime.Hour(); + tm_struct.tm_min = fTime.Minute(); + tm_struct.tm_sec = fTime.Second(); + + tm_struct.tm_year = fDate.Year() - 1900; + tm_struct.tm_mon = fDate.Month() - 1; + tm_struct.tm_mday = fDate.Day(); + + // set less 0 as we wan't use it + tm_struct.tm_isdst = -1; + + // return secs_since_jan1_1970 or -1 on error + return int32(mktime(&tm_struct)); +} + + +/*! + Sets the current date and time converted from seconds since + 1.1.1970 - 00:00:00. +*/ +void +BDateTime::SetTime_t(uint32 seconds) +{ + BTime time; + time.AddSeconds(seconds % kSecondsPerDay); + fTime.SetTime(time); + + BDate date(1970, 1, 1); + date.AddDays(seconds / kSecondsPerDay); + fDate.SetDate(date); +} + + +/*! + Returns true if this datetime is different from \c dateTime, otherwise false. +*/ +bool +BDateTime::operator!=(const BDateTime& dateTime) const +{ + return fTime != dateTime.fTime && fDate != dateTime.fDate; +} + + +/*! + Returns true if this datetime is equal to \c dateTime, otherwise false. +*/ +bool +BDateTime::operator==(const BDateTime& dateTime) const +{ + return fTime == dateTime.fTime && fDate == dateTime.fDate; +} + + +/*! + Returns true if this datetime is earlier than \c dateTime, otherwise false. +*/ +bool +BDateTime::operator<(const BDateTime& dateTime) const +{ + return fTime < dateTime.fTime && fDate < dateTime.fDate; +} + + +/*! + Returns true if this datetime is earlier than or equal to \c dateTime, + otherwise false. +*/ +bool +BDateTime::operator<=(const BDateTime& dateTime) const +{ + return fTime <= dateTime.fTime && fDate <= dateTime.fDate; +} + + +/*! + Returns true if this datetime is later than \c dateTime, otherwise false. +*/ +bool +BDateTime::operator>(const BDateTime& dateTime) const +{ + return fTime > dateTime.fTime && fDate > dateTime.fDate; +} + + +/*! + Returns true if this datetime is later than or equal to \c dateTime, + otherwise false. +*/ +bool +BDateTime::operator>=(const BDateTime& dateTime) const +{ + return fTime >= dateTime.fTime && fDate >= dateTime.fDate; +} + + +} //namespace BPrivate diff --git a/src/apps/webpositive/DateTime.h b/src/apps/webpositive/DateTime.h new file mode 100644 index 0000000000..fe92d86745 --- /dev/null +++ b/src/apps/webpositive/DateTime.h @@ -0,0 +1,215 @@ +/* + * 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 + + +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(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); + + void AddHours(int32 hours); + void AddMinutes(int32 minutes); + void AddSeconds(int32 seconds); + void AddMilliseconds(int32 milliseconds); + void 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; + void _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(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(int32 day) const; + BString ShortMonthName(int32 month) const; + + BString LongDayName(int32 day) const; + BString LongMonthName(int32 month) const; + + 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; + void SetDate(const BDate &date); + + 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_ From d4f4c7f8084f419e2cccaf450dcd18cce809de79 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:23:31 +0000 Subject: [PATCH 020/293] Added my copyright, since I've redesigned here quite a bit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@94 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index f7efb72dcb..636169c4a5 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * From ce277486d76d9577316368a8a24dbf7ef449524f Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:24:24 +0000 Subject: [PATCH 021/293] Implemented BrowsingHistoryItem class, which uses BDateTime to track when it was invoked. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@95 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 105 +++++++++++++++++++++++ src/apps/webpositive/BrowsingHistory.h | 31 +++++++ 2 files changed, 136 insertions(+) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index e70d3c0e03..d58985d9e1 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -32,10 +32,115 @@ #include #include #include +#include #include #include +BrowsingHistoryItem::BrowsingHistoryItem(const BString& url) + : m_url(url) + , m_dateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)) + , m_invokationCount(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) + m_dateTime = BDateTime(&dateTimeArchive); + archive->FindString("url", &m_url); + archive->FindUInt32("invokations", &m_invokationCount); +} + +BrowsingHistoryItem::~BrowsingHistoryItem() +{ +} + +status_t BrowsingHistoryItem::archive(BMessage* archive) const +{ + if (!archive) + return B_BAD_VALUE; + BMessage dateTimeArchive; + status_t status = m_dateTime.Archive(&dateTimeArchive); + if (status == B_OK) + status = archive->AddMessage("date time", &dateTimeArchive); + if (status == B_OK) + status = archive->AddString("url", m_url.String()); + if (status == B_OK) + status = archive->AddUInt32("invokations", m_invokationCount); + return status; +} + +BrowsingHistoryItem& BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) +{ + if (this == &other) + return *this; + + m_url = other.m_url; + m_dateTime = other.m_dateTime; + m_invokationCount = other.m_invokationCount; + + return *this; +} + +bool BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return true; + + return m_url == other.m_url && m_dateTime == other.m_dateTime + && m_invokationCount == other.m_invokationCount; +} + +bool BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const +{ + return !(*this == other); +} + +bool BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return false; + + return m_dateTime < other.m_dateTime || m_url < other.m_url; +} + +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 m_dateTime > other.m_dateTime || m_url > other.m_url; +} + +bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const +{ + return (*this == other) || (*this > other); +} + +void BrowsingHistoryItem::increaseInvokationCount() +{ + // Eventually, we may overflow... + uint32 count = m_invokationCount + 1; + if (count > m_invokationCount) + m_invokationCount = count; +} + +// #pragma mark - BrowsingHistory + BrowsingHistory BrowsingHistory::s_defaultInstance; BrowsingHistory::BrowsingHistory() diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 82ef0ba04f..b660cb30fb 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -28,9 +28,40 @@ #ifndef BrowsingHistory_h #define BrowsingHistory_h +#include "DateTime.h" #include 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 m_url; } + const BDateTime& dateTime() const { return m_dateTime; } + uint32 invokationCount() const { return m_invokationCount; } + void increaseInvokationCount(); + +private: + BString m_url; + BDateTime m_dateTime; + uint32 m_invokationCount; +}; class BrowsingHistory : public BLocker { public: From 2bff1b82035cd2f5c983136be46b282c9dc9859c Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 18:17:17 +0000 Subject: [PATCH 022/293] Wired and debugged everything to give us a basic "Go" menu, a.k.a browsing history... :-) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@98 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 94 ++++++++++++++++++++++-- src/apps/webpositive/BrowsingHistory.h | 13 +++- src/apps/webpositive/LauncherWindow.cpp | 60 ++++++++++++++- src/apps/webpositive/LauncherWindow.h | 3 + 4 files changed, 159 insertions(+), 11 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index d58985d9e1..7c5246df11 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -131,18 +132,17 @@ bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const return (*this == other) || (*this > other); } -void BrowsingHistoryItem::increaseInvokationCount() +void BrowsingHistoryItem::invoked() { // Eventually, we may overflow... uint32 count = m_invokationCount + 1; if (count > m_invokationCount) m_invokationCount = count; + m_dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); } // #pragma mark - BrowsingHistory -BrowsingHistory BrowsingHistory::s_defaultInstance; - BrowsingHistory::BrowsingHistory() : BLocker("browsing history") { @@ -150,18 +150,91 @@ BrowsingHistory::BrowsingHistory() if (openSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); - // TODO: ... + + BMessage historyItemArchive; + for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { + addItem(BrowsingHistoryItem(&historyItemArchive)); + historyItemArchive.MakeEmpty(); + } } } BrowsingHistory::~BrowsingHistory() { saveSettings(); + privateClear(); } /*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() { - return &s_defaultInstance; + static BrowsingHistory defaultInstance; + + return &defaultInstance; +} + +bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) +{ + BAutolock _(this); + + int32 count = countItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + if (item.url() == existingItem->url()) { + existingItem->invoked(); + return true; + } + if (item < *existingItem) + insertionIndex = i; + } + BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); + if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + newItem->invoked(); + saveSettings(); + + return true; +} + +int32 BrowsingHistory::BrowsingHistory::countItems() const +{ + BAutolock _(const_cast(this)); + + return m_historyItems.CountItems(); +} + +BrowsingHistoryItem BrowsingHistory::historyItemAt(int32 index) const +{ + BAutolock _(const_cast(this)); + + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAt(index)); + if (!existingItem) + return BrowsingHistoryItem(BString()); + + return BrowsingHistoryItem(*existingItem); +} + +void BrowsingHistory::clear() +{ + BAutolock _(this); + privateClear(); + saveSettings(); +} + +void BrowsingHistory::privateClear() +{ + int32 count = countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* item = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + delete item; + } + m_historyItems.MakeEmpty(); } // #pragma mark - private @@ -171,7 +244,16 @@ void BrowsingHistory::saveSettings() BFile settingsFile; if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; - // TODO: ... + 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); } } diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index b660cb30fb..00e4f3a5e7 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -29,6 +29,7 @@ #define BrowsingHistory_h #include "DateTime.h" +#include #include class BFile; @@ -55,7 +56,7 @@ public: const BString& url() const { return m_url; } const BDateTime& dateTime() const { return m_dateTime; } uint32 invokationCount() const { return m_invokationCount; } - void increaseInvokationCount(); + void invoked(); private: BString m_url; @@ -67,15 +68,23 @@ 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(); + private: BrowsingHistory(); virtual ~BrowsingHistory(); + void privateClear(); void saveSettings(); bool openSettingsFile(BFile& file, uint32 mode); private: - static BrowsingHistory s_defaultInstance; + BList m_historyItems; }; #endif // BrowsingHistory_h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7fb3a366ea..fb654ef5ac 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -33,9 +33,11 @@ #include "LauncherWindow.h" #include "AuthenticationPanel.h" +#include "BrowsingHistory.h" #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" +#include #include #include #include @@ -59,6 +61,7 @@ enum { GO_FORWARD = 'gofo', GOTO_URL = 'goul', RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', TEXT_SIZE_INCREASE = 'tsin', TEXT_SIZE_DECREASE = 'tsdc', @@ -111,6 +114,9 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); m_menuBar->AddItem(menu); + m_goMenu = new BMenu("Go"); + m_menuBar->AddItem(m_goMenu); + // Back & Forward m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); @@ -218,10 +224,13 @@ void LauncherWindow::MessageReceived(BMessage* message) case RELOAD: webView()->loadRequest(m_url->Text()); break; - case GOTO_URL: - if (m_loadedURL != m_url->Text()) - webView()->loadRequest(m_url->Text()); + case GOTO_URL: { + BString url = m_url->Text(); + message->FindString("url", &url); + if (m_loadedURL != url) + webView()->loadRequest(url.String()); break; + } case GO_BACK: webView()->goBack(); break; @@ -229,6 +238,17 @@ void LauncherWindow::MessageReceived(BMessage* message) webView()->goForward(); break; + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " + "the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); + break; + } + case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one @@ -305,6 +325,35 @@ bool LauncherWindow::QuitRequested() return false; } +void LauncherWindow::MenusBeginning() +{ + BMenuItem* menuItem; + while ((menuItem = m_goMenu->RemoveItem(0L))) + delete menuItem; + + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + int32 count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... + menuItem = new BMenuItem(historyItem.url().String(), message); + m_goMenu->AddItem(menuItem); + } + + + if (m_goMenu->CountItems() > 3) { + m_goMenu->AddSeparatorItem(); + m_goMenu->AddItem(new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY))); + } + + history->Unlock(); +} + // #pragma mark - Notification API void LauncherWindow::navigationRequested(const BString& url) @@ -393,6 +442,11 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, m_ForwardButton->SetEnabled(canGoForward); } +void LauncherWindow::updateGlobalHistory(const BString& url) +{ + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); +} + void LauncherWindow::authenticationChallenge(BMessage* message) { BString text; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ca4b8391b5..3c814f9893 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -62,6 +62,7 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + virtual void MenusBeginning(); // WebViewWindow notification API implementations virtual void navigationRequested(const BString& url); @@ -75,10 +76,12 @@ public: virtual void statusChanged(const BString& status); virtual void navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop); + virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); private: BMenuBar* m_menuBar; + BMenu* m_goMenu; BButton* m_BackButton; BButton* m_ForwardButton; BTextControl* m_url; From defb5e01c43945931205a1149b241313ce7fd983 Mon Sep 17 00:00:00 2001 From: mmlr Date: Fri, 19 Feb 2010 02:48:44 +0000 Subject: [PATCH 023/293] Fix uninitialized m_windowCount which could cause the app to close on any window close randomly (or always with libroot_debug). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@139 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index df664c7f5a..69713a886e 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -53,6 +53,7 @@ enum { LauncherApp::LauncherApp() : BApplication(kApplicationSignature) + , m_windowCount(0) , m_lastWindowFrame(100, 100, 700, 750) , m_launchRefsMessage(0) , m_initialized(false) From a62545c15526a03ae7a1cee64908f851edeeb118 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 15:47:21 +0000 Subject: [PATCH 024/293] Renamed WebProcess to WebPage. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@146 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 2 +- src/apps/webpositive/LauncherApp.cpp | 6 +++--- src/apps/webpositive/LauncherWindow.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ea0492b402..f6e94b1072 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -29,7 +29,7 @@ #include "DownloadWindow.h" #include "WebDownload.h" -#include "WebProcess.h" +#include "WebPage.h" #include #include #include diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 69713a886e..bbede28b06 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -33,7 +33,7 @@ #include "FrameView.h" #include "GraphicsContext.h" #include "LauncherWindow.h" -#include "WebProcess.h" +#include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -92,8 +92,8 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { - WebProcess::initializeOnce(); - WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + WebPage::initializeOnce(); + WebPage::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index fb654ef5ac..0e820b4ab3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -34,7 +34,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" -#include "WebProcess.h" +#include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -200,7 +200,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - webView()->webProcess()->setDownloadListener(downloadListener); + webView()->webPage()->setDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -367,7 +367,7 @@ void LauncherWindow::newWindowRequested(const BString& url) { // Always open new windows in the application thread, since // creating a WebView will try to grab the application lock. - // But our own WebProcess may already try to lock us from within + // But our own WebPage may already try to lock us from within // the application thread -> dead-lock. BMessage message(NEW_WINDOW); message.AddString("url", url); From a89e2a4b6c01aea49da2499ba57941526a622da0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 17:23:45 +0000 Subject: [PATCH 025/293] Refactoring to support multiple WebViews per WebViewWindow. There is now the notion of a current WebView. In the notification messages, carry the information which WebView it is for. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@147 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 21 ++-- src/apps/webpositive/LauncherWindow.cpp | 138 +++++++++++++++++------- src/apps/webpositive/LauncherWindow.h | 26 +++-- 3 files changed, 128 insertions(+), 57 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index bbede28b06..9503f2c3e7 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -130,15 +130,14 @@ void LauncherApp::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) break; - bool newWindow; - if (message->FindBool("new window", &newWindow) != B_OK) - newWindow = false; - WebViewWindow* webWindow = NULL; + bool openNewWindow = false; + message->FindBool("new window", &openNewWindow); + LauncherWindow* webWindow = NULL; for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); + webWindow = dynamic_cast(window); if (!webWindow) continue; - if (!newWindow) { + if (!openNewWindow) { // stop at the first window break; } @@ -146,12 +145,12 @@ void LauncherApp::MessageReceived(BMessage* message) if (webWindow) { // There should always be at least one window open. If not, maybe we are about // to quit anyway... - if (newWindow) { + if (openNewWindow) { // open a new window with an offset to the last window - webWindow->newWindowRequested(url); + newWindow(url); } else { // load the URL in the first window - webWindow->webView()->loadRequest(url.String()); + webWindow->currentWebView()->loadRequest(url.String()); } } break; @@ -218,7 +217,7 @@ void LauncherApp::RefsReceived(BMessage* message) bool LauncherApp::QuitRequested() { for (int i = 0; BWindow* window = WindowAt(i); i++) { - WebViewWindow* webWindow = dynamic_cast(window); + LauncherWindow* webWindow = dynamic_cast(window); if (!webWindow) continue; if (!webWindow->Lock()) @@ -268,7 +267,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->webView()->loadRequest(url.String()); + window->currentWebView()->loadRequest(url.String()); } // #pragma mark - diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 0e820b4ab3..4c7b208055 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -88,6 +88,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { + setCurrentWebView(new WebView("web_view")); if (toolbarPolicy == HaveToolbar) { // Menu m_menuBar = new BMenuBar("Main menu"); @@ -174,7 +175,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(webView()) + .Add(currentWebView()) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -196,11 +197,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = 0; AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(webView()) + .Add(currentWebView()) ); } - webView()->webPage()->setDownloadListener(downloadListener); + currentWebView()->webPage()->setDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -209,7 +210,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - navigationCapabilitiesChanged(false, false, false); + navigationCapabilitiesChanged(false, false, false, currentWebView()); be_app->PostMessage(WINDOW_OPENED); } @@ -222,20 +223,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - webView()->loadRequest(m_url->Text()); + currentWebView()->loadRequest(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - webView()->loadRequest(url.String()); + currentWebView()->loadRequest(url.String()); break; } case GO_BACK: - webView()->goBack(); + currentWebView()->goBack(); break; case GO_FORWARD: - webView()->goForward(); + currentWebView()->goForward(); break; case CLEAR_HISTORY: { @@ -271,26 +272,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - webView()->loadRequest(path.Path()); + currentWebView()->loadRequest(path.Path()); break; } case TEXT_SIZE_INCREASE: - webView()->increaseTextSize(); + currentWebView()->increaseTextSize(); break; case TEXT_SIZE_DECREASE: - webView()->decreaseTextSize(); + currentWebView()->decreaseTextSize(); break; case TEXT_SIZE_RESET: - webView()->resetTextSize(); + currentWebView()->resetTextSize(); break; case TEXT_FIND_NEXT: - webView()->findString(m_findTextControl->Text(), true, + currentWebView()->findString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - webView()->findString(m_findTextControl->Text(), false, + currentWebView()->findString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -309,20 +310,26 @@ void LauncherWindow::MessageReceived(BMessage* message) break; default: - WebViewWindow::MessageReceived(message); + BWindow::MessageReceived(message); break; } } bool LauncherWindow::QuitRequested() { - if (WebViewWindow::QuitRequested()) { - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); - be_app->PostMessage(&message); - return true; - } - return false; + // TODO: Check for modified form data and ask user for confirmation, etc. + + // Do this here, so WebKit tear down happens earlier. + // TODO: Iterator over all WebViews, if there are more then one... + WebView* view = currentWebView(); + view->RemoveSelf(); + delete view; + setCurrentWebView(0); + + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; } void LauncherWindow::MenusBeginning() @@ -341,7 +348,9 @@ void LauncherWindow::MenusBeginning() BMessage* message = new BMessage(GOTO_URL); message->AddString("url", historyItem.url().String()); // TODO: More sophisticated menu structure... sorted by days/weeks... - menuItem = new BMenuItem(historyItem.url().String(), message); + BString truncatedUrl(historyItem.url()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); m_goMenu->AddItem(menuItem); } @@ -356,8 +365,9 @@ void LauncherWindow::MenusBeginning() // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url) +void LauncherWindow::navigationRequested(const BString& url, WebView* view) { + // TODO: Move elsewhere, doesn't belong here. m_loadedURL = url; if (m_url) m_url->SetText(url.String()); @@ -374,22 +384,25 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegociating(const BString& url) +void LauncherWindow::loadNegociating(const BString& url, WebView* view) { BString status("Requesting: "); status << url; - statusChanged(status); + statusChanged(status, view); } -void LauncherWindow::loadTransfering(const BString& url) +void LauncherWindow::loadTransfering(const BString& url, WebView* view) { BString status("Loading: "); status << url; - statusChanged(status); + statusChanged(status, view); } -void LauncherWindow::loadProgress(float progress) +void LauncherWindow::loadProgress(float progress, WebView* view) { + if (view != currentWebView()) + return; + if (m_loadingProgressBar) { if (progress < 100 && m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Show(); @@ -397,29 +410,76 @@ void LauncherWindow::loadProgress(float progress) } } -void LauncherWindow::loadFailed(const BString& url) +void LauncherWindow::loadFailed(const BString& url, WebView* view) { + if (view != currentWebView()) + return; + BString status(url); status << " failed."; - statusChanged(status); + statusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url) +void LauncherWindow::loadFinished(const BString& url, WebView* view) { + if (view != currentWebView()) + return; + m_loadedURL = url; BString status(url); status << " finished."; - statusChanged(status); + statusChanged(status, view); if (m_url) m_url->SetText(url.String()); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::titleChanged(const BString& title) +void LauncherWindow::resizeRequested(float width, float height, WebView* view) { + if (view != currentWebView()) + return; + + // TODO: Ignore request when there is more than one WebView embedded! + + ResizeTo(width, height); +} + +void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setResizable(bool flag, WebView* view) +{ + // TODO: Ignore request when there is more than one WebView embedded! + + if (flag) + SetFlags(Flags() & ~B_NOT_RESIZABLE); + else + SetFlags(Flags() | B_NOT_RESIZABLE); +} + +void LauncherWindow::titleChanged(const BString& title, WebView* view) +{ + if (view != currentWebView()) + return; + BString windowTitle = title; if (windowTitle.Length() > 0) windowTitle << " - "; @@ -427,15 +487,21 @@ void LauncherWindow::titleChanged(const BString& title) SetTitle(windowTitle.String()); } -void LauncherWindow::statusChanged(const BString& statusText) +void LauncherWindow::statusChanged(const BString& statusText, WebView* view) { + if (view != currentWebView()) + return; + if (m_statusText) m_statusText->SetText(statusText.String()); } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop) + bool canGoForward, bool canStop, WebView* view) { + if (view != currentWebView()) + return; + if (m_BackButton) m_BackButton->SetEnabled(canGoBackward); if (m_ForwardButton) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 3c814f9893..ac0a392657 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -64,18 +64,24 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - // WebViewWindow notification API implementations - virtual void navigationRequested(const BString& url); +private: + // WebPage notification API implementations + virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegociating(const BString& url); - virtual void loadTransfering(const BString& url); - virtual void loadProgress(float progress); - virtual void loadFailed(const BString& url); - virtual void loadFinished(const BString& url); - virtual void titleChanged(const BString& title); - virtual void statusChanged(const BString& status); + virtual void loadNegociating(const BString& url, WebView* view); + virtual void loadTransfering(const BString& url, WebView* view); + virtual void loadProgress(float progress, WebView* view); + virtual void loadFailed(const BString& url, WebView* view); + virtual void loadFinished(const BString& url, WebView* view); + virtual void titleChanged(const BString& title, WebView* view); + virtual void resizeRequested(float width, float height, WebView* view); + virtual void setToolBarsVisible(bool flag, WebView* view); + virtual void setStatusBarVisible(bool flag, WebView* view); + virtual void setMenuBarVisible(bool flag, WebView* view); + virtual void setResizable(bool flag, WebView* view); + virtual void statusChanged(const BString& status, WebView* view); virtual void navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop); + bool canGoForward, bool canStop, WebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); From c9219daa51601fd635ca7c83a19eb8fbcc9a366d Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 18:29:13 +0000 Subject: [PATCH 026/293] Fixed left-over bug from refactoring. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@148 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4c7b208055..3a4171c277 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -310,7 +310,7 @@ void LauncherWindow::MessageReceived(BMessage* message) break; default: - BWindow::MessageReceived(message); + WebViewWindow::MessageReceived(message); break; } } From 82912660d55e139b15faeb4efaa5743faf7762ee Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Feb 2010 11:13:44 +0000 Subject: [PATCH 027/293] * Began renaming some public API with the B* prefix and using the Haiku coding style. (WebPage -> BWebPage). Documented what needs to go where in WebPage.h. * Moved misplaced functionality from WebFrame to BWebPage (navigation). * EditorClientHaiku takes a BWebPage pointer now, which brings a slight cleanup. * Exposed WebFrame::isEditable() to EditorClientHaiku, so isEditable() can be implemented. * Added some asserts in FrameLoaderClientHaiku according to the Gtk port and placed some debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@150 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 4 ++-- src/apps/webpositive/LauncherApp.cpp | 4 ++-- src/apps/webpositive/LauncherWindow.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index f6e94b1072..335b526a20 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -385,13 +385,13 @@ DownloadWindow::~DownloadWindow() void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { - case DOWNLOAD_ADDED: { + case B_DOWNLOAD_ADDED: { WebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadStarted(download); break; } - case DOWNLOAD_REMOVED: { + case B_DOWNLOAD_REMOVED: { WebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadFinished(download); diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 9503f2c3e7..4f01619717 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -92,8 +92,8 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { - WebPage::initializeOnce(); - WebPage::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + BWebPage::InitializeOnce(); + BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3a4171c277..b8f07ad021 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -201,7 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - currentWebView()->webPage()->setDownloadListener(downloadListener); + currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); From c14fa6263858745ec3148398b7f0cc1eac3a96ce Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 15:28:30 +0000 Subject: [PATCH 028/293] Typo/spelling corrections. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@151 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b8f07ad021..adbeea2a15 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -384,7 +384,7 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegociating(const BString& url, WebView* view) +void LauncherWindow::loadNegotiating(const BString& url, WebView* view) { BString status("Requesting: "); status << url; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ac0a392657..ff537a6be5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -68,7 +68,7 @@ private: // WebPage notification API implementations virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegociating(const BString& url, WebView* view); + virtual void loadNegotiating(const BString& url, WebView* view); virtual void loadTransfering(const BString& url, WebView* view); virtual void loadProgress(float progress, WebView* view); virtual void loadFailed(const BString& url, WebView* view); From 95b246f2a7e410b0c9924a64ae1cf06cd2754410 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 16:22:31 +0000 Subject: [PATCH 029/293] Add basic tabbed browsing support. Does not yet properly handle maintaining/switching the current URL or status bar text per-tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@152 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 134 ++++++++++++++++-------- src/apps/webpositive/LauncherWindow.h | 10 +- src/apps/webpositive/WebTabView.cpp | 57 ++++++++++ src/apps/webpositive/WebTabView.h | 52 +++++++++ 4 files changed, 204 insertions(+), 49 deletions(-) create mode 100644 src/apps/webpositive/WebTabView.cpp create mode 100644 src/apps/webpositive/WebTabView.h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index adbeea2a15..9e2e3f5e72 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" #include "WebPage.h" +#include "WebTabView.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -88,16 +89,26 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { - setCurrentWebView(new WebView("web_view")); + m_tabView = new WebTabView("tabview", BMessenger(this)); + WebView *webView = new WebView("web_view"); + m_tabView->AddTab(webView); + m_tabView->TabAt(0L)->SetLabel("New Tab"); + setCurrentWebView(webView); + if (toolbarPolicy == HaveToolbar) { // Menu m_menuBar = new BMenuBar("Main menu"); BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); - menu->AddItem(newItem); + BMenu *newMenu = new BMenu("New"); + BMenuItem* newItem = new BMenuItem("Window", newWindowMessage, 'N'); + newMenu->AddItem(newItem); newItem->SetTarget(be_app); + newItem = new BMenuItem("Tab", new BMessage(NEW_TAB), 'T'); + newMenu->AddItem(newItem); + newItem->SetTarget(this); + menu->AddItem(newMenu); menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); @@ -175,7 +186,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(currentWebView()) + .Add(m_tabView) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -240,20 +251,20 @@ void LauncherWindow::MessageReceived(BMessage* message) break; case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) - break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " - "the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->clear(); + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " + "the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); break; } case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. type_code type; int32 countFound; if (message->GetInfo("refs", &type, &countFound) != B_OK @@ -309,6 +320,24 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; + case NEW_TAB: + { + m_tabView->AddTab(new WebView("web_view")); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); + m_tabView->DrawTabs(); + m_tabView->Select(m_tabView->CountTabs() - 1); + break; + } + + case TAB_CHANGED: + { + int32 index = message->FindInt32("index"); + setCurrentWebView(dynamic_cast( + m_tabView->ViewForTab(index))); + updateTitle(m_tabView->TabAt(index)->Label()); + break; + } + default: WebViewWindow::MessageReceived(message); break; @@ -334,9 +363,9 @@ bool LauncherWindow::QuitRequested() void LauncherWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = m_goMenu->RemoveItem(0L))) - delete menuItem; + BMenuItem* menuItem; + while ((menuItem = m_goMenu->RemoveItem(0L))) + delete menuItem; BrowsingHistory* history = BrowsingHistory::defaultInstance(); if (!history->Lock()) @@ -344,14 +373,14 @@ void LauncherWindow::MenusBeginning() int32 count = history->countItems(); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... BString truncatedUrl(historyItem.url()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - m_goMenu->AddItem(menuItem); + m_goMenu->AddItem(menuItem); } @@ -367,7 +396,7 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::navigationRequested(const BString& url, WebView* view) { - // TODO: Move elsewhere, doesn't belong here. + // TODO: Move elsewhere, doesn't belong here. m_loadedURL = url; if (m_url) m_url->SetText(url.String()); @@ -400,8 +429,8 @@ void LauncherWindow::loadTransfering(const BString& url, WebView* view) void LauncherWindow::loadProgress(float progress, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_loadingProgressBar) { if (progress < 100 && m_loadingProgressBar->IsHidden()) @@ -412,8 +441,8 @@ void LauncherWindow::loadProgress(float progress, WebView* view) void LauncherWindow::loadFailed(const BString& url, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; BString status(url); status << " failed."; @@ -424,8 +453,8 @@ void LauncherWindow::loadFailed(const BString& url, WebView* view) void LauncherWindow::loadFinished(const BString& url, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; m_loadedURL = url; BString status(url); @@ -439,8 +468,8 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) void LauncherWindow::resizeRequested(float width, float height, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; // TODO: Ignore request when there is more than one WebView embedded! @@ -449,19 +478,19 @@ void LauncherWindow::resizeRequested(float width, float height, WebView* view) void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } @@ -477,20 +506,24 @@ void LauncherWindow::setResizable(bool flag, WebView* view) void LauncherWindow::titleChanged(const BString& title, WebView* view) { - if (view != currentWebView()) - return; + for (int32 i = 0; i < m_tabView->CountTabs(); i++) + { + if (m_tabView->ViewForTab(i) == view) { + m_tabView->TabAt(i)->SetLabel(title); + m_tabView->DrawTabs(); + break; + } + } + if (view != currentWebView()) + return; - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + updateTitle(title); } void LauncherWindow::statusChanged(const BString& statusText, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_statusText) m_statusText->SetText(statusText.String()); @@ -499,8 +532,8 @@ void LauncherWindow::statusChanged(const BString& statusText, WebView* view) void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_BackButton) m_BackButton->SetEnabled(canGoBackward); @@ -510,7 +543,7 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, void LauncherWindow::updateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } void LauncherWindow::authenticationChallenge(BMessage* message) @@ -539,3 +572,12 @@ void LauncherWindow::authenticationChallenge(BMessage* message) reply.AddBool("rememberCredentials", rememberCredentials); message->SendReply(&reply); } + +void LauncherWindow::updateTitle(const BString& title) +{ + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ff537a6be5..ca325b4bc5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -39,6 +39,7 @@ class BLayoutItem; class BMenu; class BStatusBar; class BStringView; +class BTabView; class BTextControl; class WebView; @@ -48,9 +49,10 @@ enum ToolbarPolicy { }; enum { - NEW_WINDOW = 'nwnd', - WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc', + NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' }; @@ -84,6 +86,7 @@ private: bool canGoForward, bool canStop, WebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); + void updateTitle(const BString &title); private: BMenuBar* m_menuBar; @@ -97,6 +100,7 @@ private: BLayoutItem* m_findGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; + BTabView* m_tabView; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp new file mode 100644 index 0000000000..fc454953c7 --- /dev/null +++ b/src/apps/webpositive/WebTabView.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Rene Gollent + * + * 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 "WebTabView.h" + +WebTabView::WebTabView(const char *name, const BMessenger& target) + : BTabView(name) + , m_target(target) +{ +} + +WebTabView::~WebTabView(void) +{ +} + +void +WebTabView::Select(int32 tab) +{ + BTabView::Select(tab); + BMessage message(TAB_CHANGED); + message.AddInt32("index", tab); + m_target.SendMessage(&message); +} + +const BMessenger& WebTabView::Target(void) const +{ + return m_target; +} + +void WebTabView::SetTarget(const BMessenger& target) +{ + m_target = target; +} diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h new file mode 100644 index 0000000000..7cd7964afb --- /dev/null +++ b/src/apps/webpositive/WebTabView.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Rene Gollent + * + * 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 WebTabView_h +#define WebTabView_h + +#include +#include + +enum { + TAB_CHANGED = 'tcha' +}; + +class WebTabView : public BTabView { +public: + WebTabView(const char *name, const BMessenger& target); + virtual ~WebTabView(void); + virtual void Select(int32 tab); + + const BMessenger& Target(void) const; + void SetTarget(const BMessenger& target); + +private: + BMessenger m_target; +}; + +#define WebTabView_h +#endif // WebTabView_h From 5eba20dc102e37cf1d2675d6cd05c40d6d6868cd Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 18:46:53 +0000 Subject: [PATCH 030/293] Add close tab support via cmd+shift+w. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@153 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 18 ++++++++++++++++-- src/apps/webpositive/LauncherWindow.h | 1 - 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 9e2e3f5e72..e1ff5e2ba4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -4,6 +4,7 @@ * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus * Copyright (C) 2010 Michael Lotz + * Copyright (C) 2010 Rene Gollent * * All rights reserved. * @@ -72,6 +73,9 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', + + NEW_TAB = 'ntab', + CLOSE_TAB = 'ctab' }; using namespace WebCore; @@ -109,7 +113,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, newMenu->AddItem(newItem); newItem->SetTarget(this); menu->AddItem(newMenu); - menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + BMenu *closeMenu = new BMenu("Close"); + closeMenu->AddItem(new BMenuItem("Window", new BMessage(B_QUIT_REQUESTED), 'W')); + closeMenu->AddItem(new BMenuItem("Tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddItem(closeMenu); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); @@ -324,11 +331,18 @@ void LauncherWindow::MessageReceived(BMessage* message) { m_tabView->AddTab(new WebView("web_view")); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); - m_tabView->DrawTabs(); m_tabView->Select(m_tabView->CountTabs() - 1); break; } + case CLOSE_TAB: + { + if (m_tabView->CountTabs() > 0) { + delete m_tabView->RemoveTab(m_tabView->FocusTab()); + } + break; + } + case TAB_CHANGED: { int32 index = message->FindInt32("index"); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ca325b4bc5..803b7f2517 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -50,7 +50,6 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', - NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' From d311e279f536e28f24e65d9c1edc52e772e9d76c Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 18:59:51 +0000 Subject: [PATCH 031/293] Clean up tabs properly on quit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@154 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e1ff5e2ba4..92ec37d911 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -349,6 +349,7 @@ void LauncherWindow::MessageReceived(BMessage* message) setCurrentWebView(dynamic_cast( m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); + m_url->TextView()->SetText(currentWebView()->mainFrameURL()); break; } @@ -364,9 +365,9 @@ bool LauncherWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. // TODO: Iterator over all WebViews, if there are more then one... - WebView* view = currentWebView(); - view->RemoveSelf(); - delete view; + while (m_tabView->CountTabs() > 0) { + delete m_tabView->RemoveTab(0L); + } setCurrentWebView(0); BMessage message(WINDOW_CLOSED); From 75845de732ffa2ca970d6b9d4e1197769616ee7e Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 19:52:10 +0000 Subject: [PATCH 032/293] Add mechanism for asking LauncherApp to create a web view to ensure new view creation always happens in the main thread. Fixes assert failure when creating a new tab with debug builds. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@155 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 6 ++++++ src/apps/webpositive/LauncherApp.h | 4 ++++ src/apps/webpositive/LauncherWindow.cpp | 13 ++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 4f01619717..367894b11a 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -165,6 +165,12 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); break; } + case CREATE_WEBVIEW: { + BMessage reply; + reply.AddPointer("view", new WebView("web_view")); + message->SendReply(&reply); + break; + } case WINDOW_OPENED: m_windowCount++; break; diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 636169c4a5..8be0c4ebb1 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -36,6 +36,10 @@ class BFile; class DownloadWindow; class LauncherWindow; +enum { + CREATE_WEBVIEW = 'crwb' +}; + class LauncherApp : public BApplication { public: LauncherApp(); diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 92ec37d911..12c5c460e9 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" +#include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -329,9 +330,14 @@ void LauncherWindow::MessageReceived(BMessage* message) case NEW_TAB: { - m_tabView->AddTab(new WebView("web_view")); + BMessage reply; + be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); + WebView *view = NULL; + reply.FindPointer("view", reinterpret_cast(&view)); + m_tabView->AddTab(view); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); m_tabView->Select(m_tabView->CountTabs() - 1); + navigationCapabilitiesChanged(false, false, false, currentWebView()); break; } @@ -350,6 +356,11 @@ void LauncherWindow::MessageReceived(BMessage* message) m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); + BWebPage *page = currentWebView()->webPage(); +// bool canGoForward = page->CanGoInDirection(1); +// bool canGoBackward = page->CanGoInDirection(-1); +// navigationCapabilitiesChanged(canGoForward, canGoBackward, false, +// currentWebView()); break; } From 14ad7bdb25ce28b1be7d4bdff21f2013df2407c1 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 19:59:29 +0000 Subject: [PATCH 033/293] Focus address bar when creating a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@156 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 12c5c460e9..97a0fbd30a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -338,6 +338,7 @@ void LauncherWindow::MessageReceived(BMessage* message) m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); m_tabView->Select(m_tabView->CountTabs() - 1); navigationCapabilitiesChanged(false, false, false, currentWebView()); + m_url->MakeFocus(true); break; } From 5478dd2992636f251b24de249a421a2c82554396 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Feb 2010 20:03:11 +0000 Subject: [PATCH 034/293] * Asthetical improvements with the new tab view. * Actually set the target on the tab view, so that we change urls when switching tabs. * Move all New/Close items to the top-level, since I find it slightly too awkward to reach them otherwise. * Misc coding style fixes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@157 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 50 +++++++++++-------------- src/apps/webpositive/LauncherWindow.h | 4 +- src/apps/webpositive/WebTabView.cpp | 11 ++++-- src/apps/webpositive/WebTabView.h | 4 +- 4 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 97a0fbd30a..e6adae4285 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -95,9 +95,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { m_tabView = new WebTabView("tabview", BMessenger(this)); - WebView *webView = new WebView("web_view"); + WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(0L)->SetLabel("New Tab"); + m_tabView->setTarget(BMessenger(this)); setCurrentWebView(webView); if (toolbarPolicy == HaveToolbar) { @@ -106,20 +107,17 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); - BMenu *newMenu = new BMenu("New"); - BMenuItem* newItem = new BMenuItem("Window", newWindowMessage, 'N'); - newMenu->AddItem(newItem); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); newItem->SetTarget(be_app); - newItem = new BMenuItem("Tab", new BMessage(NEW_TAB), 'T'); - newMenu->AddItem(newItem); + newItem = new BMenuItem("New tab", new BMessage(NEW_TAB), 'T'); + menu->AddItem(newItem); newItem->SetTarget(this); - menu->AddItem(newMenu); - BMenu *closeMenu = new BMenu("Close"); - closeMenu->AddItem(new BMenuItem("Window", new BMessage(B_QUIT_REQUESTED), 'W')); - closeMenu->AddItem(new BMenuItem("Tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); - menu->AddItem(closeMenu); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -152,7 +150,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 16)); + m_statusText->SetExplicitMinSize(BSize(150, 15)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -171,7 +169,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, new BMessage(TEXT_FIND_NEXT)); m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_findTextControl) .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) @@ -193,10 +191,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(button, 3, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(m_tabView) .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) @@ -328,30 +326,26 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case NEW_TAB: - { + case NEW_TAB: { BMessage reply; be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); WebView *view = NULL; reply.FindPointer("view", reinterpret_cast(&view)); m_tabView->AddTab(view); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); m_tabView->Select(m_tabView->CountTabs() - 1); navigationCapabilitiesChanged(false, false, false, currentWebView()); m_url->MakeFocus(true); break; } - case CLOSE_TAB: - { - if (m_tabView->CountTabs() > 0) { + case CLOSE_TAB: { + if (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(m_tabView->FocusTab()); - } break; } - case TAB_CHANGED: - { + case TAB_CHANGED: { int32 index = message->FindInt32("index"); setCurrentWebView(dynamic_cast( m_tabView->ViewForTab(index))); @@ -377,9 +371,8 @@ bool LauncherWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. // TODO: Iterator over all WebViews, if there are more then one... - while (m_tabView->CountTabs() > 0) { + while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); - } setCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -533,8 +526,7 @@ void LauncherWindow::setResizable(bool flag, WebView* view) void LauncherWindow::titleChanged(const BString& title, WebView* view) { - for (int32 i = 0; i < m_tabView->CountTabs(); i++) - { + for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { m_tabView->TabAt(i)->SetLabel(title); m_tabView->DrawTabs(); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 803b7f2517..43e00b4700 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -39,8 +39,8 @@ class BLayoutItem; class BMenu; class BStatusBar; class BStringView; -class BTabView; class BTextControl; +class WebTabView; class WebView; enum ToolbarPolicy { @@ -99,7 +99,7 @@ private: BLayoutItem* m_findGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; - BTabView* m_tabView; + WebTabView* m_tabView; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index fc454953c7..a45ccc38c2 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -27,18 +27,21 @@ #include "WebTabView.h" +#include + WebTabView::WebTabView(const char *name, const BMessenger& target) : BTabView(name) , m_target(target) { + if (BGroupLayout* layout = dynamic_cast(GetLayout())) + layout->SetInsets(2, 2 + TabHeight() - 1, 2, 2); } WebTabView::~WebTabView(void) { } -void -WebTabView::Select(int32 tab) +void WebTabView::Select(int32 tab) { BTabView::Select(tab); BMessage message(TAB_CHANGED); @@ -46,12 +49,12 @@ WebTabView::Select(int32 tab) m_target.SendMessage(&message); } -const BMessenger& WebTabView::Target(void) const +const BMessenger& WebTabView::target() const { return m_target; } -void WebTabView::SetTarget(const BMessenger& target) +void WebTabView::setTarget(const BMessenger& target) { m_target = target; } diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 7cd7964afb..ac85a460c1 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -41,8 +41,8 @@ public: virtual ~WebTabView(void); virtual void Select(int32 tab); - const BMessenger& Target(void) const; - void SetTarget(const BMessenger& target); + const BMessenger& target() const; + void setTarget(const BMessenger& target); private: BMessenger m_target; From 14c76a65466a543522170992ed253a7b399b07e2 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 12:49:11 +0000 Subject: [PATCH 035/293] Use arrow icons for th enavigation buttons. The IconButton class is a slightly extended version of the LaunchBox version (added TrimIcon() method). Will go away when/if the browser is moved into the Haiku source tree. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@159 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 924 ++++++++++++++++++++++++ src/apps/webpositive/IconButton.h | 134 ++++ src/apps/webpositive/IconUtils.h | 80 ++ src/apps/webpositive/Launcher.rdef | 36 + src/apps/webpositive/LauncherWindow.cpp | 18 +- src/apps/webpositive/LauncherWindow.h | 5 +- 6 files changed, 1188 insertions(+), 9 deletions(-) create mode 100644 src/apps/webpositive/IconButton.cpp create mode 100644 src/apps/webpositive/IconButton.h create mode 100644 src/apps/webpositive/IconUtils.h diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp new file mode 100644 index 0000000000..317754aecd --- /dev/null +++ b/src/apps/webpositive/IconButton.cpp @@ -0,0 +1,924 @@ +/* + * Copyright 2006-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(®ion); + region.Exclude(bitmap->Bounds().OffsetByCopy(point)); + ConstrainClippingRegion(®ion); + } + // 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; + +printf("check\n"); + size_t size; + const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID, + &size); + if (data != NULL) { +printf("found resource\n"); + 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(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 + dBits[nOffset + 0] = fBits[fOffset + 0]; + dBits[nOffset + 1] = fBits[fOffset + 1]; + dBits[nOffset + 2] = fBits[fOffset + 2]; + dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + // disabled bits have less contrast (lame method...) + dcBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); + dcBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); + dcBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); + dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + } + 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(); +} diff --git a/src/apps/webpositive/IconButton.h b/src/apps/webpositive/IconButton.h new file mode 100644 index 0000000000..2876dd8cfd --- /dev/null +++ b/src/apps/webpositive/IconButton.h @@ -0,0 +1,134 @@ +/* + * Copyright 2006-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +/** 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 +#include +#include + +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 diff --git a/src/apps/webpositive/IconUtils.h b/src/apps/webpositive/IconUtils.h new file mode 100644 index 0000000000..fdcfbd946f --- /dev/null +++ b/src/apps/webpositive/IconUtils.h @@ -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 + +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 diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef index 3165079460..fd1410f0e3 100644 --- a/src/apps/webpositive/Launcher.rdef +++ b/src/apps/webpositive/Launcher.rdef @@ -252,3 +252,39 @@ resource vector_icon { $"44013402360000000000000000360000485000466000" }; +resource(201) #'VICN' array { + $"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" + $"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF" + $"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585" + $"C70200060238E8A83647FBBA8E2D3D42294AF6F7496CE200047BB8FF0694DE02" + $"0006023957BB3923F0BC39AC3C5E604AA873475AB1000592DAFD67CBFF04FF49" + $"080A092E3C3A53424C484F5047503A4435442B3A300A072E3C3A533A48484F48" + $"403A3A3A300A043A303A3A4435442B0A033A483A53424C0A044840484F504750" + $"3A0A043A3A4435503A48400803C125B7D43AB99FB8D3BE0E08023A3A4840070A" + $"0001001001178400040A010101000A020102000A030103000A040104000A0501" + $"05000A06020607100117812004" +}; + +resource(202) #'VICN' array { + $"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" + $"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF" + $"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD" + $"FF04FF49050A0A2E423A483A524847503F432A3A2F3A3136302E350A0748473A" + $"2F3A392E352E423A483A520A043A2F4847503F432A0A042E3536303A313A3908" + $"0536B9932FBB773B3A3BB939C0E5B755050A0001001001178400040A01010100" + $"0A020102000A030103000A040104100117812004" +}; + +resource(203) #'VICN' array { + $"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9" + $"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF" + $"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468" + $"9C020006023AC62E392AB63B6BA0BCFF0B49DAAA4AAE4500046FA7FF2BA5E502" + $"0006023A1CB834EBA6383E33BD3E8D499DE44A647800ACE2FFFD6DCCFF04FF49" + $"080A09523A48533F503C532E4C2E3E3A363A2B482E0A07523A485348473C533C" + $"43483A482E0A04482E483A3A363A2B0A03484748533F500A043C433C532E4C2E" + $"3E0A04483A3A362E3E3C430802BD8FB795C2BDB8E008023C43B8C7BF0D070A00" + $"01001001178400040A040101000A020102000A030103000A010104000A050105" + $"000A06020607100117812004" +}; + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e6adae4285..1a453aaf27 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" +#include "IconButton.h" #include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" @@ -42,6 +43,7 @@ #include "WebViewConstants.h" #include #include +#include #include #include #include @@ -136,8 +138,13 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_menuBar->AddItem(m_goMenu); // Back & Forward - m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); - m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); + m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + m_BackButton->SetIcon(201); + m_BackButton->TrimIcon(); + + m_ForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + m_ForwardButton->SetIcon(202); + m_ForwardButton->TrimIcon(); // URL m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); @@ -347,11 +354,10 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast( - m_tabView->ViewForTab(index))); + setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); - BWebPage *page = currentWebView()->webPage(); +// BWebPage* page = currentWebView()->webPage(); // bool canGoForward = page->CanGoInDirection(1); // bool canGoBackward = page->CanGoInDirection(-1); // navigationCapabilitiesChanged(canGoForward, canGoBackward, false, @@ -480,8 +486,6 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) BString status(url); status << " finished."; statusChanged(status, view); - if (m_url) - m_url->SetText(url.String()); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 43e00b4700..64d0a18045 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -40,6 +40,7 @@ class BMenu; class BStatusBar; class BStringView; class BTextControl; +class IconButton; class WebTabView; class WebView; @@ -90,8 +91,8 @@ private: private: BMenuBar* m_menuBar; BMenu* m_goMenu; - BButton* m_BackButton; - BButton* m_ForwardButton; + IconButton* m_BackButton; + IconButton* m_ForwardButton; BTextControl* m_url; BString m_loadedURL; BStringView* m_statusText; From 56bdbcc74ec1eb329ec771bea4c10425e5eacfd3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:13:03 +0000 Subject: [PATCH 036/293] Fixed deadlocks when adding a new tab. The WebView needs to be created int the app thread indeed, but the app thread may already be blocking on the window lock, we we cannot wait for a synchronous reply from the app in the window thread. Refactored the tab creation and reused it in the LauncherWindow constructor. Added the ability to load a URL in the new tab right away. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@160 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 22 +++++++++--- src/apps/webpositive/LauncherApp.h | 5 +-- src/apps/webpositive/LauncherWindow.cpp | 47 +++++++++++++------------ src/apps/webpositive/LauncherWindow.h | 3 ++ 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 367894b11a..22c8eb05f6 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -165,10 +165,13 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); break; } - case CREATE_WEBVIEW: { - BMessage reply; - reply.AddPointer("view", new WebView("web_view")); - message->SendReply(&reply); + case NEW_TAB: { + LauncherWindow* window; + if (message->FindPointer("window", reinterpret_cast(&window)) != B_OK) + break; + BString url; + message->FindString("url", &url); + newTab(window, url); break; } case WINDOW_OPENED: @@ -276,6 +279,17 @@ void LauncherApp::newWindow(const BString& url) window->currentWebView()->loadRequest(url.String()); } +void LauncherApp::newTab(LauncherWindow* window, const BString& url) +{ + if (!window->Lock()) + return; + window->newTab(); + window->Unlock(); + + if (url.Length()) + window->currentWebView()->loadRequest(url.String()); +} + // #pragma mark - int main(int, char**) diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 8be0c4ebb1..69b60bcc78 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -36,10 +36,6 @@ class BFile; class DownloadWindow; class LauncherWindow; -enum { - CREATE_WEBVIEW = 'crwb' -}; - class LauncherApp : public BApplication { public: LauncherApp(); @@ -55,6 +51,7 @@ public: private: bool openSettingsFile(BFile& file, uint32 mode); void newWindow(const BString& url); + void newTab(LauncherWindow* window, const BString& url); int m_windowCount; BRect m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 1a453aaf27..d434b7934a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -77,7 +77,6 @@ enum { TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - NEW_TAB = 'ntab', CLOSE_TAB = 'ctab' }; @@ -97,11 +96,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { m_tabView = new WebTabView("tabview", BMessenger(this)); - WebView* webView = new WebView("web_view"); - m_tabView->AddTab(webView); - m_tabView->TabAt(0L)->SetLabel("New Tab"); m_tabView->setTarget(BMessenger(this)); - setCurrentWebView(webView); if (toolbarPolicy == HaveToolbar) { // Menu @@ -112,9 +107,12 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); menu->AddItem(newItem); newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(NEW_TAB), 'T'); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newItem = new BMenuItem("New tab", newTabMessage, 'T'); menu->AddItem(newItem); - newItem->SetTarget(this); + newItem->SetTarget(be_app); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); @@ -220,11 +218,15 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = 0; m_loadingProgressBar = 0; + WebView* webView = new WebView("web_view"); + setCurrentWebView(webView); + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) .Add(currentWebView()) ); } + newTab(); currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -234,8 +236,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - navigationCapabilitiesChanged(false, false, false, currentWebView()); - be_app->PostMessage(WINDOW_OPENED); } @@ -333,21 +333,9 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case NEW_TAB: { - BMessage reply; - be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); - WebView *view = NULL; - reply.FindPointer("view", reinterpret_cast(&view)); - m_tabView->AddTab(view); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - m_tabView->Select(m_tabView->CountTabs() - 1); - navigationCapabilitiesChanged(false, false, false, currentWebView()); - m_url->MakeFocus(true); - break; - } - case CLOSE_TAB: { - if (m_tabView->CountTabs() > 0) + printf("CLOSE_TAB\n"); + if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->FocusTab()); break; } @@ -418,6 +406,19 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } +void LauncherWindow::newTab() +{ + // Executed in app thread (new BWebPage needs to be created in app thread). + WebView* webView = new WebView("web_view"); + m_tabView->AddTab(webView); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); + navigationCapabilitiesChanged(false, false, false, webView); + if (m_url) + m_url->MakeFocus(true); +} + // #pragma mark - Notification API void LauncherWindow::navigationRequested(const BString& url, WebView* view) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 64d0a18045..b113541683 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -51,6 +51,7 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' @@ -66,6 +67,8 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); + void newTab(); + private: // WebPage notification API implementations virtual void navigationRequested(const BString& url, WebView* view); From 63d76ab872832ad7a57f1bd166d54aac425381cf Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:20:57 +0000 Subject: [PATCH 037/293] Middle clicking links will open new tabs, but will not select them. Matches Firefox behavior. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@161 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 11 +++++----- src/apps/webpositive/LauncherApp.h | 2 +- src/apps/webpositive/LauncherWindow.cpp | 27 ++++++++++++++++--------- src/apps/webpositive/LauncherWindow.h | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 22c8eb05f6..5b60e09a66 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -171,7 +171,9 @@ void LauncherApp::MessageReceived(BMessage* message) break; BString url; message->FindString("url", &url); - newTab(window, url); + bool select = false; + message->FindBool("select", &select); + newTab(window, url, select); break; } case WINDOW_OPENED: @@ -279,15 +281,12 @@ void LauncherApp::newWindow(const BString& url) window->currentWebView()->loadRequest(url.String()); } -void LauncherApp::newTab(LauncherWindow* window, const BString& url) +void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) { if (!window->Lock()) return; - window->newTab(); + window->newTab(url, select); window->Unlock(); - - if (url.Length()) - window->currentWebView()->loadRequest(url.String()); } // #pragma mark - diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 69b60bcc78..15dabba6a2 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -51,7 +51,7 @@ public: private: bool openSettingsFile(BFile& file, uint32 mode); void newWindow(const BString& url); - void newTab(LauncherWindow* window, const BString& url); + void newTab(LauncherWindow* window, const BString& url, bool select); int m_windowCount; BRect m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d434b7934a..d1ef7f15eb 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -226,7 +226,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - newTab(); + newTab("", true); currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -406,17 +406,23 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } -void LauncherWindow::newTab() +void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); - navigationCapabilitiesChanged(false, false, false, webView); - if (m_url) - m_url->MakeFocus(true); + + if (url.Length()) + webView->loadRequest(url.String()); + + if (select) { + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); + navigationCapabilitiesChanged(false, false, false, webView); + if (m_url) + m_url->MakeFocus(true); + } } // #pragma mark - Notification API @@ -434,9 +440,12 @@ void LauncherWindow::newWindowRequested(const BString& url) // Always open new windows in the application thread, since // creating a WebView will try to grab the application lock. // But our own WebPage may already try to lock us from within - // the application thread -> dead-lock. - BMessage message(NEW_WINDOW); + // the application thread -> dead-lock. Thus we can't wait for + // a reply here. + BMessage message(NEW_TAB); + message.AddPointer("window", this); message.AddString("url", url); + message.AddBool("select", false); be_app->PostMessage(&message); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index b113541683..e660d8d1df 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -67,7 +67,7 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - void newTab(); + void newTab(const BString& url, bool select); private: // WebPage notification API implementations From fafcdf7cd1897e868b9fcecf0114fcf68bb4fe52 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:34:54 +0000 Subject: [PATCH 038/293] Introduced BWebPage::ResendNotifications(). This is a simple way for the window to update itself to the properties of a page when switching pages. Resolves deadlock problem with BWebPage::CanGoInDirection(), which I've removed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@162 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d1ef7f15eb..6c5100a246 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -345,11 +345,9 @@ void LauncherWindow::MessageReceived(BMessage* message) setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); -// BWebPage* page = currentWebView()->webPage(); -// bool canGoForward = page->CanGoInDirection(1); -// bool canGoBackward = page->CanGoInDirection(-1); -// navigationCapabilitiesChanged(canGoForward, canGoBackward, false, -// currentWebView()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + currentWebView()->webPage()->ResendNotifications(); break; } From 714edff6e1c1219ac19df3d4dda33e5d695db570 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:43:27 +0000 Subject: [PATCH 039/293] Select the new tab when creating it via the menu. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@163 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 6c5100a246..b1ba5135b0 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -110,6 +110,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); newItem = new BMenuItem("New tab", newTabMessage, 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); From d3d066c32244cd5587fe792e7bf869cf26b9e3f8 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:48:07 +0000 Subject: [PATCH 040/293] BTabView doesn't properly trigger a relayout when adding a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@164 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b1ba5135b0..09b484f0fc 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -411,6 +411,8 @@ void LauncherWindow::newTab(const BString& url, bool select) WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); + // TODO: Remove when BTabView is fixed... + m_tabView->InvalidateLayout(); if (url.Length()) webView->loadRequest(url.String()); From df621688c56c7c0c2ae2578de9b21136fc404435 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 15:30:49 +0000 Subject: [PATCH 041/293] Fix closing tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@165 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 09b484f0fc..db0c838c66 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -337,7 +337,7 @@ void LauncherWindow::MessageReceived(BMessage* message) case CLOSE_TAB: { printf("CLOSE_TAB\n"); if (m_tabView->CountTabs() > 1) - delete m_tabView->RemoveTab(m_tabView->FocusTab()); + delete m_tabView->RemoveTab(m_tabView->Selection()); break; } From b6ffb2048f4681bbfcc6493c4cd5f25c1197570f Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 15:31:11 +0000 Subject: [PATCH 042/293] Removed stray debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@166 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index db0c838c66..068e5c76f4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -335,7 +335,6 @@ void LauncherWindow::MessageReceived(BMessage* message) break; case CLOSE_TAB: { - printf("CLOSE_TAB\n"); if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->Selection()); break; From d05b8e1a31a94bf2fdc5784adb5c5663a55b8d1b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 21 Feb 2010 16:16:46 +0000 Subject: [PATCH 043/293] Change window/tab management shortcuts: - cmd+w now closes the active tab. If the tab is the only one remaining, the window is closed. - cmd+shift+w closes the window, regardless of tab count. Whitespace cleanups. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@167 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 068e5c76f4..8255555a73 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -115,8 +115,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(newItem); newItem->SetTarget(be_app); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); @@ -337,6 +337,8 @@ void LauncherWindow::MessageReceived(BMessage* message) case CLOSE_TAB: { if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->Selection()); + else + PostMessage(B_QUIT_REQUESTED); break; } @@ -406,19 +408,19 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { - // Executed in app thread (new BWebPage needs to be created in app thread). + // Executed in app thread (new BWebPage needs to be created in app thread). WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... m_tabView->InvalidateLayout(); - if (url.Length()) - webView->loadRequest(url.String()); + if (url.Length()) + webView->loadRequest(url.String()); if (select) { - m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); navigationCapabilitiesChanged(false, false, false, webView); if (m_url) m_url->MakeFocus(true); @@ -543,7 +545,7 @@ void LauncherWindow::titleChanged(const BString& title, WebView* view) for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { m_tabView->TabAt(i)->SetLabel(title); - m_tabView->DrawTabs(); + m_tabView->DrawTabs(); break; } } From 7a9d9c2cf8af614e84de04e78093f3acb96bad74 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:23:55 +0000 Subject: [PATCH 044/293] Set the "no border" look to avoid the double frame around the WebView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@169 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index a45ccc38c2..ff59b0f1ca 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -33,8 +33,7 @@ WebTabView::WebTabView(const char *name, const BMessenger& target) : BTabView(name) , m_target(target) { - if (BGroupLayout* layout = dynamic_cast(GetLayout())) - layout->SetInsets(2, 2 + TabHeight() - 1, 2, 2); + SetBorder(B_NO_BORDER); } WebTabView::~WebTabView(void) From 0bcb05f98d1429abbb764249195863e408b93047 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:30:54 +0000 Subject: [PATCH 045/293] Forgot to commit this. Polishes no-border BTabView look. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@173 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 8255555a73..1f979bfe63 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -156,7 +156,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 15)); + m_statusText->SetExplicitMinSize(BSize(150, 16)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -175,7 +175,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, new BMessage(TEXT_FIND_NEXT)); m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_findTextControl) .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) @@ -200,7 +200,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, // .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(m_tabView) .Add(findGroup) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) From e7bd43d9ca7bef43777c1670353f04c6d9762a2f Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:36:46 +0000 Subject: [PATCH 046/293] Place the thread priority tweak somewhere where it actually works. This makes HaikuLauncher totally usable under heavy system load. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@174 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 5b60e09a66..04d0b5650b 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -59,8 +59,6 @@ LauncherApp::LauncherApp() , m_initialized(false) , m_downloadWindow(0) { - // Since we will essentially run the GUI... - set_thread_priority(Thread(), B_DISPLAY_PRIORITY); } LauncherApp::~LauncherApp() @@ -92,6 +90,9 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::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); From 58a9dd9dfe861e69bc05fccb868a4180ed276a88 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Feb 2010 15:52:17 +0000 Subject: [PATCH 047/293] * Moved exposed classes from WebCore out of WebFrame.h, reintroduced WebFramePrivate to hide WebCore internals from the public API. FrameLoadClientHaiku: * Don't send load requested in policy decision method dispatchDecidePolicyForNavigationAction(). Calling the policy function with PolicyUse will already trigger the load correctly. Ignore the request when we want to load it into a new window/frame instead. * Subframes returned false in canHandleRequest(). This was what stopped stuff being loaded into sub frames! Finally frames and iframes are working. Praise Ingo's Debugger once more! * Renamed LOAD_TRANSFERING to LOAD_COMMITED, since WebCore means that the loader and policy stuff have come to the conclusion to finally load the URL. So that's also the event which needs to update the URL text control. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@182 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 2 -- src/apps/webpositive/LauncherWindow.cpp | 10 +++++----- src/apps/webpositive/LauncherWindow.h | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 317754aecd..36cc142bac 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -373,12 +373,10 @@ IconButton::SetIcon(int32 resourceID) if (status != B_OK) return status; -printf("check\n"); size_t size; const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID, &size); if (data != NULL) { -printf("found resource\n"); BBitmap bitmap(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_RGBA32); status = bitmap.InitCheck(); if (status != B_OK) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 1f979bfe63..3c74d2422c 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -431,10 +431,6 @@ void LauncherWindow::newTab(const BString& url, bool select) void LauncherWindow::navigationRequested(const BString& url, WebView* view) { - // TODO: Move elsewhere, doesn't belong here. - m_loadedURL = url; - if (m_url) - m_url->SetText(url.String()); } void LauncherWindow::newWindowRequested(const BString& url) @@ -458,8 +454,12 @@ void LauncherWindow::loadNegotiating(const BString& url, WebView* view) statusChanged(status, view); } -void LauncherWindow::loadTransfering(const BString& url, WebView* view) +void LauncherWindow::loadCommited(const BString& url, WebView* view) { + // This hook is invoked when the load is commited. + if (m_url) + m_url->SetText(url.String()); + BString status("Loading: "); status << url; statusChanged(status, view); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e660d8d1df..745cf70189 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -74,7 +74,7 @@ private: virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); virtual void loadNegotiating(const BString& url, WebView* view); - virtual void loadTransfering(const BString& url, WebView* view); + virtual void loadCommited(const BString& url, WebView* view); virtual void loadProgress(float progress, WebView* view); virtual void loadFailed(const BString& url, WebView* view); virtual void loadFinished(const BString& url, WebView* view); From 57b6a0fc1b3532a58a3677288af8dbf6328e3c69 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:20:33 +0000 Subject: [PATCH 048/293] * The next round of API cleanup. WebView was renamed to BWebView. Some API needed be ChromeClientHaiku has been moved to BWebPage. WebView.h is now clean and would be ready for the Haiku tree. * BWebPage no longer invalidates the BWebView when a resize happens, WebCore already takes care of that. * BWebView draws a white area in Draw() when the offscreen view is not clean. since no unnecessary invalidation happens, this doesn't result in any flicker and basically only speeds up perceived loading speed, since the web page is immediately white upon program launch. * Since WebTabView does not draw a frame, it removes B_FULL_UPDATE_ON_RESIZE and thereby completely avoids flickering upon window resize. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@190 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 4 +- src/apps/webpositive/LauncherWindow.cpp | 79 +++++++++++++------------ src/apps/webpositive/LauncherWindow.h | 30 +++++----- src/apps/webpositive/WebTabView.cpp | 1 + 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 04d0b5650b..112b528b4b 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -151,7 +151,7 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); } else { // load the URL in the first window - webWindow->currentWebView()->loadRequest(url.String()); + webWindow->currentWebView()->LoadURL(url.String()); } } break; @@ -279,7 +279,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->currentWebView()->loadRequest(url.String()); + window->currentWebView()->LoadURL(url.String()); } void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3c74d2422c..b721e8d313 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -219,7 +219,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = 0; m_loadingProgressBar = 0; - WebView* webView = new WebView("web_view"); + BWebView* webView = new BWebView("web_view"); setCurrentWebView(webView); AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) @@ -228,7 +228,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } newTab("", true); - currentWebView()->webPage()->SetDownloadListener(downloadListener); + currentWebView()->WebPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -248,20 +248,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - currentWebView()->loadRequest(m_url->Text()); + currentWebView()->LoadURL(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - currentWebView()->loadRequest(url.String()); + currentWebView()->LoadURL(url.String()); break; } case GO_BACK: - currentWebView()->goBack(); + currentWebView()->GoBack(); break; case GO_FORWARD: - currentWebView()->goForward(); + currentWebView()->GoForward(); break; case CLEAR_HISTORY: { @@ -297,26 +297,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - currentWebView()->loadRequest(path.Path()); + currentWebView()->LoadURL(path.Path()); break; } case TEXT_SIZE_INCREASE: - currentWebView()->increaseTextSize(); + currentWebView()->IncreaseTextSize(); break; case TEXT_SIZE_DECREASE: - currentWebView()->decreaseTextSize(); + currentWebView()->DecreaseTextSize(); break; case TEXT_SIZE_RESET: - currentWebView()->resetTextSize(); + currentWebView()->ResetTextSize(); break; case TEXT_FIND_NEXT: - currentWebView()->findString(m_findTextControl->Text(), true, + currentWebView()->FindString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - currentWebView()->findString(m_findTextControl->Text(), false, + currentWebView()->FindString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -344,12 +344,12 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); + setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); - m_url->TextView()->SetText(currentWebView()->mainFrameURL()); + m_url->SetText(currentWebView()->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. - currentWebView()->webPage()->ResendNotifications(); + currentWebView()->WebPage()->ResendNotifications(); break; } @@ -409,14 +409,14 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). - WebView* webView = new WebView("web_view"); + BWebView* webView = new BWebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... m_tabView->InvalidateLayout(); if (url.Length()) - webView->loadRequest(url.String()); + webView->LoadURL(url.String()); if (select) { m_tabView->Select(m_tabView->CountTabs() - 1); @@ -429,14 +429,14 @@ void LauncherWindow::newTab(const BString& url, bool select) // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url, WebView* view) +void LauncherWindow::navigationRequested(const BString& url, BWebView* view) { } void LauncherWindow::newWindowRequested(const BString& url) { // Always open new windows in the application thread, since - // creating a WebView will try to grab the application lock. + // creating a BWebView will try to grab the application lock. // But our own WebPage may already try to lock us from within // the application thread -> dead-lock. Thus we can't wait for // a reply here. @@ -447,15 +447,20 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegotiating(const BString& url, WebView* view) +void LauncherWindow::loadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; statusChanged(status, view); } -void LauncherWindow::loadCommited(const BString& url, WebView* view) +void LauncherWindow::loadCommited(const BString& url, BWebView* view) { + if (view != currentWebView()) + return; + + m_loadedURL = url; + // This hook is invoked when the load is commited. if (m_url) m_url->SetText(url.String()); @@ -465,7 +470,7 @@ void LauncherWindow::loadCommited(const BString& url, WebView* view) statusChanged(status, view); } -void LauncherWindow::loadProgress(float progress, WebView* view) +void LauncherWindow::loadProgress(float progress, BWebView* view) { if (view != currentWebView()) return; @@ -477,7 +482,7 @@ void LauncherWindow::loadProgress(float progress, WebView* view) } } -void LauncherWindow::loadFailed(const BString& url, WebView* view) +void LauncherWindow::loadFailed(const BString& url, BWebView* view) { if (view != currentWebView()) return; @@ -489,7 +494,7 @@ void LauncherWindow::loadFailed(const BString& url, WebView* view) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url, WebView* view) +void LauncherWindow::loadFinished(const BString& url, BWebView* view) { if (view != currentWebView()) return; @@ -502,37 +507,37 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) m_loadingProgressBar->Hide(); } -void LauncherWindow::resizeRequested(float width, float height, WebView* view) +void LauncherWindow::resizeRequested(float width, float height, BWebView* view) { if (view != currentWebView()) return; - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! ResizeTo(width, height); } -void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) +void LauncherWindow::setToolBarsVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) +void LauncherWindow::setStatusBarVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) +void LauncherWindow::setMenuBarVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setResizable(bool flag, WebView* view) +void LauncherWindow::setResizable(bool flag, BWebView* view) { - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! if (flag) SetFlags(Flags() & ~B_NOT_RESIZABLE); @@ -540,7 +545,7 @@ void LauncherWindow::setResizable(bool flag, WebView* view) SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::titleChanged(const BString& title, WebView* view) +void LauncherWindow::titleChanged(const BString& title, BWebView* view) { for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { @@ -555,7 +560,7 @@ void LauncherWindow::titleChanged(const BString& title, WebView* view) updateTitle(title); } -void LauncherWindow::statusChanged(const BString& statusText, WebView* view) +void LauncherWindow::statusChanged(const BString& statusText, BWebView* view) { if (view != currentWebView()) return; @@ -565,7 +570,7 @@ void LauncherWindow::statusChanged(const BString& statusText, WebView* view) } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, WebView* view) + bool canGoForward, bool canStop, BWebView* view) { if (view != currentWebView()) return; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 745cf70189..f1879290fa 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -42,7 +42,7 @@ class BStringView; class BTextControl; class IconButton; class WebTabView; -class WebView; +class BWebView; enum ToolbarPolicy { HaveToolbar, @@ -71,22 +71,22 @@ public: private: // WebPage notification API implementations - virtual void navigationRequested(const BString& url, WebView* view); + virtual void navigationRequested(const BString& url, BWebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegotiating(const BString& url, WebView* view); - virtual void loadCommited(const BString& url, WebView* view); - virtual void loadProgress(float progress, WebView* view); - virtual void loadFailed(const BString& url, WebView* view); - virtual void loadFinished(const BString& url, WebView* view); - virtual void titleChanged(const BString& title, WebView* view); - virtual void resizeRequested(float width, float height, WebView* view); - virtual void setToolBarsVisible(bool flag, WebView* view); - virtual void setStatusBarVisible(bool flag, WebView* view); - virtual void setMenuBarVisible(bool flag, WebView* view); - virtual void setResizable(bool flag, WebView* view); - virtual void statusChanged(const BString& status, WebView* view); + virtual void loadNegotiating(const BString& url, BWebView* view); + virtual void loadCommited(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 titleChanged(const BString& title, 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, WebView* view); + bool canGoForward, bool canStop, BWebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); void updateTitle(const BString &title); diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index ff59b0f1ca..b4ead81c6c 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -34,6 +34,7 @@ WebTabView::WebTabView(const char *name, const BMessenger& target) , m_target(target) { SetBorder(B_NO_BORDER); + SetFlags(Flags() & ~B_FULL_UPDATE_ON_RESIZE); } WebTabView::~WebTabView(void) From d54c477ad18cac663d4c135007985c051f571679 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:34:53 +0000 Subject: [PATCH 049/293] Properly set the download listener on new tabs. This fixes the Downloads window not popping up for subsequent tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@192 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 4 +++- src/apps/webpositive/LauncherWindow.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b721e8d313..5fc38abc75 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -94,6 +94,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, : WebViewWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + , m_downloadListener(downloadListener) { m_tabView = new WebTabView("tabview", BMessenger(this)); m_tabView->setTarget(BMessenger(this)); @@ -228,7 +229,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } newTab("", true); - currentWebView()->WebPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -410,6 +410,8 @@ void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); + webView->WebPage()->SetDownloadListener(m_downloadListener); + m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index f1879290fa..d0f8fe0a2c 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -31,6 +31,7 @@ #define LauncherWindow_h #include "WebViewWindow.h" +#include #include class BButton; @@ -92,6 +93,7 @@ private: void updateTitle(const BString &title); private: + BMessenger m_downloadListener; BMenuBar* m_menuBar; BMenu* m_goMenu; IconButton* m_BackButton; From feba54b70cafab7c24a621053b83cc51bbacb2d4 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:39:17 +0000 Subject: [PATCH 050/293] Invalidate the BTabView when new tabs are added. Works around new tabs not showing immediately after they have been created, some pages don't set the title either, so then the tab still would't show. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@193 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 5fc38abc75..fe5f9b2c8a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -415,7 +415,7 @@ void LauncherWindow::newTab(const BString& url, bool select) m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... - m_tabView->InvalidateLayout(); + m_tabView->Invalidate(); if (url.Length()) webView->LoadURL(url.String()); From 054c42b1b9c907fca81f251cbf779c024cf4c64c Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 18:33:22 +0000 Subject: [PATCH 051/293] Renamed WebViewWindow to BWebWindow and converted the API to Haiku coding guide lines. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@195 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 4 +- src/apps/webpositive/LauncherWindow.cpp | 98 ++++++++++++------------- src/apps/webpositive/LauncherWindow.h | 39 +++++----- 3 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 112b528b4b..5ebef34120 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -151,7 +151,7 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); } else { // load the URL in the first window - webWindow->currentWebView()->LoadURL(url.String()); + webWindow->CurrentWebView()->LoadURL(url.String()); } } break; @@ -279,7 +279,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->currentWebView()->LoadURL(url.String()); + window->CurrentWebView()->LoadURL(url.String()); } void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index fe5f9b2c8a..f89037dc13 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -91,7 +91,7 @@ static BLayoutItem* layoutItemFor(BView* view) LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) - : WebViewWindow(frame, "HaikuLauncher", + : BWebWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) @@ -221,10 +221,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = 0; BWebView* webView = new BWebView("web_view"); - setCurrentWebView(webView); + SetCurrentWebView(webView); AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(currentWebView()) + .Add(CurrentWebView()) ); } @@ -248,20 +248,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - currentWebView()->LoadURL(m_url->Text()); + CurrentWebView()->LoadURL(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - currentWebView()->LoadURL(url.String()); + CurrentWebView()->LoadURL(url.String()); break; } case GO_BACK: - currentWebView()->GoBack(); + CurrentWebView()->GoBack(); break; case GO_FORWARD: - currentWebView()->GoForward(); + CurrentWebView()->GoForward(); break; case CLEAR_HISTORY: { @@ -297,26 +297,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - currentWebView()->LoadURL(path.Path()); + CurrentWebView()->LoadURL(path.Path()); break; } case TEXT_SIZE_INCREASE: - currentWebView()->IncreaseTextSize(); + CurrentWebView()->IncreaseTextSize(); break; case TEXT_SIZE_DECREASE: - currentWebView()->DecreaseTextSize(); + CurrentWebView()->DecreaseTextSize(); break; case TEXT_SIZE_RESET: - currentWebView()->ResetTextSize(); + CurrentWebView()->ResetTextSize(); break; case TEXT_FIND_NEXT: - currentWebView()->FindString(m_findTextControl->Text(), true, + CurrentWebView()->FindString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - currentWebView()->FindString(m_findTextControl->Text(), false, + CurrentWebView()->FindString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -344,17 +344,17 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); + SetCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); - m_url->SetText(currentWebView()->MainFrameURL()); + m_url->SetText(CurrentWebView()->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. - currentWebView()->WebPage()->ResendNotifications(); + CurrentWebView()->WebPage()->ResendNotifications(); break; } default: - WebViewWindow::MessageReceived(message); + BWebWindow::MessageReceived(message); break; } } @@ -367,7 +367,7 @@ bool LauncherWindow::QuitRequested() // TODO: Iterator over all WebViews, if there are more then one... while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); - setCurrentWebView(0); + SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -422,8 +422,8 @@ void LauncherWindow::newTab(const BString& url, bool select) if (select) { m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); - navigationCapabilitiesChanged(false, false, false, webView); + SetCurrentWebView(webView); + NavigationCapabilitiesChanged(false, false, false, webView); if (m_url) m_url->MakeFocus(true); } @@ -431,11 +431,11 @@ void LauncherWindow::newTab(const BString& url, bool select) // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url, BWebView* view) +void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::newWindowRequested(const BString& url) +void LauncherWindow::NewWindowRequested(const BString& url) { // Always open new windows in the application thread, since // creating a BWebView will try to grab the application lock. @@ -449,16 +449,16 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegotiating(const BString& url, BWebView* view) +void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; - statusChanged(status, view); + StatusChanged(status, view); } -void LauncherWindow::loadCommited(const BString& url, BWebView* view) +void LauncherWindow::LoadCommited(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; m_loadedURL = url; @@ -469,12 +469,12 @@ void LauncherWindow::loadCommited(const BString& url, BWebView* view) BString status("Loading: "); status << url; - statusChanged(status, view); + StatusChanged(status, view); } -void LauncherWindow::loadProgress(float progress, BWebView* view) +void LauncherWindow::LoadProgress(float progress, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_loadingProgressBar) { @@ -484,34 +484,34 @@ void LauncherWindow::loadProgress(float progress, BWebView* view) } } -void LauncherWindow::loadFailed(const BString& url, BWebView* view) +void LauncherWindow::LoadFailed(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; BString status(url); status << " failed."; - statusChanged(status, view); + StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url, BWebView* view) +void LauncherWindow::LoadFinished(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; m_loadedURL = url; BString status(url); status << " finished."; - statusChanged(status, view); + StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::resizeRequested(float width, float height, BWebView* view) +void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; // TODO: Ignore request when there is more than one BWebView embedded! @@ -519,25 +519,25 @@ void LauncherWindow::resizeRequested(float width, float height, BWebView* view) ResizeTo(width, height); } -void LauncherWindow::setToolBarsVisible(bool flag, BWebView* view) +void LauncherWindow::SetToolBarsVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setStatusBarVisible(bool flag, BWebView* view) +void LauncherWindow::SetStatusBarVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setMenuBarVisible(bool flag, BWebView* view) +void LauncherWindow::SetMenuBarVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setResizable(bool flag, BWebView* view) +void LauncherWindow::SetResizable(bool flag, BWebView* view) { // TODO: Ignore request when there is more than one BWebView embedded! @@ -547,7 +547,7 @@ void LauncherWindow::setResizable(bool flag, BWebView* view) SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::titleChanged(const BString& title, BWebView* view) +void LauncherWindow::TitleChanged(const BString& title, BWebView* view) { for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { @@ -556,25 +556,25 @@ void LauncherWindow::titleChanged(const BString& title, BWebView* view) break; } } - if (view != currentWebView()) + if (view != CurrentWebView()) return; updateTitle(title); } -void LauncherWindow::statusChanged(const BString& statusText, BWebView* view) +void LauncherWindow::StatusChanged(const BString& statusText, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_statusText) m_statusText->SetText(statusText.String()); } -void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, +void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_BackButton) @@ -583,12 +583,12 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, m_ForwardButton->SetEnabled(canGoForward); } -void LauncherWindow::updateGlobalHistory(const BString& url) +void LauncherWindow::UpdateGlobalHistory(const BString& url) { BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -void LauncherWindow::authenticationChallenge(BMessage* message) +void LauncherWindow::AuthenticationChallenge(BMessage* message) { BString text; bool rememberCredentials = false; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index d0f8fe0a2c..c85530ec49 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -30,7 +30,7 @@ #ifndef LauncherWindow_h #define LauncherWindow_h -#include "WebViewWindow.h" +#include "WebWindow.h" #include #include @@ -58,7 +58,7 @@ enum { SHOW_DOWNLOAD_WINDOW = 'sdwd' }; -class LauncherWindow : public WebViewWindow { +class LauncherWindow : public BWebWindow { public: LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy = HaveToolbar); @@ -72,24 +72,25 @@ public: private: // WebPage notification API implementations - virtual void navigationRequested(const BString& url, BWebView* view); - virtual void newWindowRequested(const BString& url); - virtual void loadNegotiating(const BString& url, BWebView* view); - virtual void loadCommited(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 titleChanged(const BString& title, 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, + virtual void NavigationRequested(const BString& url, BWebView* view); + virtual void NewWindowRequested(const BString& url); + virtual void LoadNegotiating(const BString& url, BWebView* view); + virtual void LoadCommited(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 TitleChanged(const BString& title, 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 void authenticationChallenge(BMessage* challenge); + virtual void UpdateGlobalHistory(const BString& url); + virtual void AuthenticationChallenge(BMessage* challenge); + void updateTitle(const BString &title); private: From c516096e8eb664f0b44242354cc2f8ae179745a9 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 19:48:35 +0000 Subject: [PATCH 052/293] * Refactored WebDownload into BWebDownload and BPrivate::WebDownloadPrivate. * Fixed a bug where the "Remove Finished" button in the downloads window would be wrongly disabled whenever a new download started. * Implemented cancelling downloads. * Prepared restarting downloads as far as the GUI goes. Need to research this first how a download can be triggered independently from anything else in WebCore... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@196 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 70 ++++++++++++++++++------- src/apps/webpositive/DownloadWindow.h | 6 +-- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 335b526a20..248e3bde44 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ enum { REMOVE_FINISHED_DOWNLOADS = 'rmfd', OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', REMOVE_DOWNLOAD = 'rmdn', SAVE_SETTINGS = 'svst' }; @@ -123,12 +126,12 @@ public: class DownloadProgressView : public BGridView { public: - DownloadProgressView(WebDownload* download) + DownloadProgressView(BWebDownload* download) : BGridView(8, 3) , m_download(download) - , m_url(download->url()) - , m_path(download->path()) - , m_expectedSize(download->expectedSize()) + , m_url(download->URL()) + , m_path(download->Path()) + , m_expectedSize(download->ExpectedSize()) { } @@ -170,10 +173,18 @@ public: else m_iconView = new IconView(archive); - m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); - m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); - m_button1->SetEnabled(m_download == NULL); - m_button2->SetEnabled(m_download == NULL); + if (!m_download && m_statusBar->CurrentValue() < 100) + m_button1 = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); + else { + m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + m_button1->SetEnabled(m_download == NULL); + } + if (m_download) + m_button2 = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); + else { + m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + m_button2->SetEnabled(m_download == NULL); + } layout->SetInsets(8, 5, 5, 6); layout->AddView(m_iconView, 0, 0, 1, 2); @@ -201,7 +212,7 @@ public: virtual void AttachedToWindow() { if (m_download) - m_download->setProgressListener(BMessenger(this)); + m_download->SetProgressListener(BMessenger(this)); m_button1->SetTarget(this); m_button2->SetTarget(this); } @@ -225,7 +236,7 @@ public: virtual void MessageReceived(BMessage* message) { switch (message->what) { - case WebDownload::DOWNLOAD_PROGRESS: { + case B_DOWNLOAD_PROGRESS: { float progress; if (message->FindFloat("progress", &progress) == B_OK) m_statusBar->SetTo(progress); @@ -244,6 +255,15 @@ public: } break; } + case RESTART_DOWNLOAD: + // TODO: + break; + + case CANCEL_DOWNLOAD: + m_download->Cancel(); + downloadCanceled(); + break; + case REMOVE_DOWNLOAD: { Window()->PostMessage(SAVE_SETTINGS); RemoveSelf(); @@ -256,7 +276,7 @@ public: } } - WebDownload* download() const + BWebDownload* download() const { return m_download; } @@ -270,6 +290,19 @@ public: { m_download = NULL; m_button1->SetEnabled(true); + m_button2->SetLabel("Remove"); + m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + m_button2->SetEnabled(true); + } + + void downloadCanceled() + { + m_download = NULL; + m_button1->SetLabel("Restart"); + m_button1->SetMessage(new BMessage(RESTART_DOWNLOAD)); + m_button1->SetEnabled(true); + m_button2->SetLabel("Remove"); + m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); m_button2->SetEnabled(true); } @@ -278,7 +311,7 @@ private: BStatusBar* m_statusBar; SmallButton* m_button1; SmallButton* m_button2; - WebDownload* m_download; + BWebDownload* m_download; BString m_url; BPath m_path; off_t m_expectedSize; @@ -386,13 +419,13 @@ void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { case B_DOWNLOAD_ADDED: { - WebDownload* download; + BWebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadStarted(download); break; } case B_DOWNLOAD_REMOVED: { - WebDownload* download; + BWebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadFinished(download); break; @@ -416,7 +449,7 @@ bool DownloadWindow::QuitRequested() return false; } -void DownloadWindow::downloadStarted(WebDownload* download) +void DownloadWindow::downloadStarted(BWebDownload* download) { int32 finishedCount = 0; int32 index = 0; @@ -425,11 +458,12 @@ void DownloadWindow::downloadStarted(WebDownload* download) DownloadProgressView* view = dynamic_cast(item->View()); if (!view) continue; - if (view->url() == download->url()) { + if (view->url() == download->URL()) { index = i; view->RemoveSelf(); delete view; - } + } else if (!view->download()) + finishedCount++; } m_removeFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); @@ -443,7 +477,7 @@ void DownloadWindow::downloadStarted(WebDownload* download) Show(); } -void DownloadWindow::downloadFinished(WebDownload* download) +void DownloadWindow::downloadFinished(BWebDownload* download) { int32 finishedCount = 0; for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index e03fce4a3e..c7819ffdec 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -33,7 +33,7 @@ class BButton; class BFile; class BGroupLayout; -class WebDownload; +class BWebDownload; class DownloadWindow : public BWindow { public: @@ -44,8 +44,8 @@ public: virtual bool QuitRequested(); private: - void downloadStarted(WebDownload* download); - void downloadFinished(WebDownload* download); + void downloadStarted(BWebDownload* download); + void downloadFinished(BWebDownload* download); void removeFinishedDownloads(); void saveSettings(); void loadSettings(); From ce869c629ba44e90bfe808d136625c32226ba91f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 21:00:55 +0000 Subject: [PATCH 053/293] Selecting or not selecting the newly opened tab never worked, since the "select" field was added to the NEW_WINDOW_REQUESTED message, and not passed on to the internal NEW_TAB message. Fixed this, and also added a check for the tertiary mouse button for regular navigation actions. This means clicking links with the middle mouse button opens in a background tab regard less if it would have opened a new page when clicked with the primary button. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@199 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 5 +++-- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index f89037dc13..61522109f1 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -408,6 +408,7 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { +printf("newTab(%s, %d)\n", url.String(), select); // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); webView->WebPage()->SetDownloadListener(m_downloadListener); @@ -435,7 +436,7 @@ void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::NewWindowRequested(const BString& url) +void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) { // Always open new windows in the application thread, since // creating a BWebView will try to grab the application lock. @@ -445,7 +446,7 @@ void LauncherWindow::NewWindowRequested(const BString& url) BMessage message(NEW_TAB); message.AddPointer("window", this); message.AddString("url", url); - message.AddBool("select", false); + message.AddBool("select", primaryAction); be_app->PostMessage(&message); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index c85530ec49..d2ad03c5cd 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -73,7 +73,7 @@ public: private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, BWebView* view); - virtual void NewWindowRequested(const BString& url); + virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommited(const BString& url, BWebView* view); virtual void LoadProgress(float progress, BWebView* view); From 16ccf622ab727d14fd5b98e774977a9f1393a6c9 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 09:20:53 +0000 Subject: [PATCH 054/293] Removed forgotten debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@207 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 61522109f1..3452583c51 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -408,7 +408,6 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { -printf("newTab(%s, %d)\n", url.String(), select); // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); webView->WebPage()->SetDownloadListener(m_downloadListener); From 1da75c0bed505b0000a8fccc3d9a7beab60363db Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:30:39 +0000 Subject: [PATCH 055/293] Implemented "Stop Loading" feature, designed icon, added button and necessary wiring to arrive at BWebFrame::StopLoading(). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@211 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/Launcher.rdef | 13 +++++++++++++ src/apps/webpositive/LauncherWindow.cpp | 20 +++++++++++++++++--- src/apps/webpositive/LauncherWindow.h | 1 + 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef index fd1410f0e3..fee9516509 100644 --- a/src/apps/webpositive/Launcher.rdef +++ b/src/apps/webpositive/Launcher.rdef @@ -288,3 +288,16 @@ resource(203) #'VICN' array { $"000A06020607100117812004" }; +resource(204) #'VICN' array { + $"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E" + $"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D" + $"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478" + $"7700FF9090FFFF757504FF440A0A0C2E4C364E3C4742524A5440434A3842353C" + $"BE1B36312E2E38400A0636313C3C40434A54504E402E0A03364E3E483C470A04" + $"483FC712BADE4A3840430A042E2E3631402E382C0A0442354A38C712BADE4AB9" + $"EC0A0E2E4C364EBEB6C37042524A54504E483FC712BADE4AB9EC4335402E382C" + $"2E2E384008022FB8A0BCC3B80708033C3C42364ABA120802BCA9BFF3B8D3C47B" + $"060A0001061001178400040A020101000A03020302000A010100000A04020504" + $"000A0503070809100117810004" +}; + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3452583c51..f3cfbbfc6c 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -64,6 +64,7 @@ enum { GO_BACK = 'goba', GO_FORWARD = 'gofo', + STOP = 'stop', GOTO_URL = 'goul', RELOAD = 'reld', CLEAR_HISTORY = 'clhs', @@ -137,7 +138,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_goMenu = new BMenu("Go"); m_menuBar->AddItem(m_goMenu); - // Back & Forward + // Back, Forward & Stop m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); m_BackButton->SetIcon(201); m_BackButton->TrimIcon(); @@ -146,6 +147,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_ForwardButton->SetIcon(202); m_ForwardButton->TrimIcon(); + m_StopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + m_StopButton->SetIcon(204); + m_StopButton->TrimIcon(); + // URL m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); m_url->SetDivider(50.0); @@ -194,8 +199,9 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) - .Add(m_url, 2, 0) - .Add(button, 3, 0) + .Add(m_StopButton, 2, 0) + .Add(m_url, 3, 0) + .Add(button, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) // .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -263,6 +269,9 @@ void LauncherWindow::MessageReceived(BMessage* message) case GO_FORWARD: CurrentWebView()->GoForward(); break; + case STOP: + CurrentWebView()->StopLoading(); + break; case CLEAR_HISTORY: { BrowsingHistory* history = BrowsingHistory::defaultInstance(); @@ -507,6 +516,9 @@ void LauncherWindow::LoadFinished(const BString& url, BWebView* view) StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); + + NavigationCapabilitiesChanged(m_BackButton->IsEnabled(), + m_ForwardButton->IsEnabled(), false, view); } void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) @@ -581,6 +593,8 @@ void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, m_BackButton->SetEnabled(canGoBackward); if (m_ForwardButton) m_ForwardButton->SetEnabled(canGoForward); + if (m_StopButton) + m_StopButton->SetEnabled(canStop); } void LauncherWindow::UpdateGlobalHistory(const BString& url) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index d2ad03c5cd..b9ff488050 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -99,6 +99,7 @@ private: BMenu* m_goMenu; IconButton* m_BackButton; IconButton* m_ForwardButton; + IconButton* m_StopButton; BTextControl* m_url; BString m_loadedURL; BStringView* m_statusText; From 9db22c336b87369f3ec99eab664e5a134e17d807 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:46:28 +0000 Subject: [PATCH 056/293] Make it much more obvious when icon buttons are disabled. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@212 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 36cc142bac..3ccf1c13b3 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -820,15 +820,21 @@ IconButton::_MakeBitmaps(const BBitmap* bitmap) cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); cBits[nOffset + 3] = fBits[fOffset + 3]; // disabled bits have less opacity - dBits[nOffset + 0] = fBits[fOffset + 0]; - dBits[nOffset + 1] = fBits[fOffset + 1]; - dBits[nOffset + 2] = fBits[fOffset + 2]; - dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + + uint8 grey = ((uint16)nBits[nOffset + 0] + nBits[nOffset + 1] + + nBits[nOffset + 2]) / 3; + 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)(nBits[nOffset + 0] * 0.8); - dcBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); - dcBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); - dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + 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; From f16ed908beb203e13d7a9ac785c03e698f755ad4 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:49:38 +0000 Subject: [PATCH 057/293] What the heck... use the correct weighting for calculating the average grey. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@213 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 3ccf1c13b3..5cd2ede604 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -821,8 +821,9 @@ IconButton::_MakeBitmaps(const BBitmap* bitmap) cBits[nOffset + 3] = fBits[fOffset + 3]; // disabled bits have less opacity - uint8 grey = ((uint16)nBits[nOffset + 0] + nBits[nOffset + 1] - + nBits[nOffset + 2]) / 3; + 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; From 9397a29aafc3929d472484e7a782657e7154b3e2 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 14:16:06 +0000 Subject: [PATCH 058/293] Use the document look for the LauncherWindow and adjust the layout accordinly. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@214 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index f3cfbbfc6c..5ab6a965fc 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -93,7 +93,7 @@ static BLayoutItem* layoutItemFor(BView* view) LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, "HaikuLauncher", - B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { @@ -162,7 +162,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 16)); + m_statusText->SetExplicitMinSize(BSize(150, 12)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -172,7 +172,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = new BStatusBar("progress"); m_loadingProgressBar->SetMaxValue(100); m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(10); + m_loadingProgressBar->SetBarHeight(12); const float kInsetSpacing = 5; const float kElementSpacing = 7; @@ -211,6 +211,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) ); From 5afb1a0f0c1b9a8d935eb6c1de96ef12a087364d Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 25 Feb 2010 15:33:01 +0000 Subject: [PATCH 059/293] Spelling fix. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@216 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 5ab6a965fc..7752ac0eb3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -466,7 +466,7 @@ void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) StatusChanged(status, view); } -void LauncherWindow::LoadCommited(const BString& url, BWebView* view) +void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) { if (view != CurrentWebView()) return; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index b9ff488050..ba7b611bc2 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -75,7 +75,7 @@ private: virtual void NavigationRequested(const BString& url, BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void LoadNegotiating(const BString& url, BWebView* view); - virtual void LoadCommited(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); From 4978460d4c30ef99888faa5b5ccff23aae316d4d Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 18:50:51 +0000 Subject: [PATCH 060/293] Implement creating new pages properly. This fixes content submission on haiku-os.org and probably a few other things. Basically, we were creating the new pages ourselves in dispatchDecidePolicyForNewWindowAction(), but we were meant to implement dispatchCreatePage() instead. Now, what we do is similar for the Qt port, only better (found a bug in Arora): When the user clicked with the tertiary mouse button, we create the window ourselves, as before, and otherwise always have WebCore create the page instead. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@218 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 10 ++++++++-- src/apps/webpositive/LauncherWindow.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7752ac0eb3..4f0dcc143a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -416,10 +416,11 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } -void LauncherWindow::newTab(const BString& url, bool select) +void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) { // Executed in app thread (new BWebPage needs to be created in app thread). - BWebView* webView = new BWebView("web_view"); + if (!webView) + webView = new BWebView("web view"); webView->WebPage()->SetDownloadListener(m_downloadListener); m_tabView->AddTab(webView); @@ -459,6 +460,11 @@ void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) be_app->PostMessage(&message); } +void LauncherWindow::NewPageCreated(BWebView* view) +{ + newTab(BString(), true, view); +} + void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ba7b611bc2..97b28f1123 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -68,12 +68,13 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - void newTab(const BString& url, bool select); + void newTab(const BString& url, bool select, BWebView* webView = 0); private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); + virtual void NewPageCreated(BWebView* view); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, BWebView* view); virtual void LoadProgress(float progress, BWebView* view); From 64f8c067354e3e23a3a0d4dcdc9de8345bc2fd36 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 08:53:10 +0000 Subject: [PATCH 061/293] Fix crash on program exit. Always good to use defensive programming techniques... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@225 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4f0dcc143a..4a014a62ef 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -353,13 +353,22 @@ void LauncherWindow::MessageReceived(BMessage* message) } case TAB_CHANGED: { - int32 index = message->FindInt32("index"); - SetCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); - updateTitle(m_tabView->TabAt(index)->Label()); - m_url->SetText(CurrentWebView()->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - CurrentWebView()->WebPage()->ResendNotifications(); + // This message may be received also when the last tab closed, i.e. with index == -1. + int32 index = -1; + message->FindInt32("index", &index); + BWebView* webView = dynamic_cast(m_tabView->ViewForTab(index)); + SetCurrentWebView(webView); + BTab* tab = m_tabView->TabAt(index); + if (tab) + updateTitle(tab->Label()); + else + updateTitle(""); + if (webView) { + m_url->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } break; } From 1c3a676322a4891d01cc8928594a0c3a96a0d8af Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 08:55:29 +0000 Subject: [PATCH 062/293] Fixed comment, the TODO was already resolved. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@226 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4a014a62ef..af877d99ca 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -382,8 +382,8 @@ bool LauncherWindow::QuitRequested() { // TODO: Check for modified form data and ask user for confirmation, etc. + // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. - // TODO: Iterator over all WebViews, if there are more then one... while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); SetCurrentWebView(0); From 72664707fa7568f6e44b493717bef1791e3453ae Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 19:02:24 +0000 Subject: [PATCH 063/293] Implemented a completely new tab view framework: * Tabs are only visible when there are more than one. * Tabs have close buttons. * Much more flexible, adding scrolling and left/right buttons when there are more tabs than room will be easy. Also drag&drop of tabs. I've tested this quite a bit, hopefully there are no regressions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@228 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 70 +- src/apps/webpositive/LauncherWindow.h | 6 +- src/apps/webpositive/WebTabView.cpp | 987 +++++++++++++++++++++++- src/apps/webpositive/WebTabView.h | 52 +- 4 files changed, 1055 insertions(+), 60 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index af877d99ca..908c4a1582 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -77,8 +77,6 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - - CLOSE_TAB = 'ctab' }; using namespace WebCore; @@ -97,8 +95,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { - m_tabView = new WebTabView("tabview", BMessenger(this)); - m_tabView->setTarget(BMessenger(this)); + m_tabManager = new TabManager(BMessenger(this)); if (toolbarPolicy == HaveToolbar) { // Menu @@ -196,6 +193,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(m_menuBar) + .Add(m_tabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) @@ -204,8 +202,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(button, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(m_tabView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(m_tabManager->ContainerView()) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -219,6 +217,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_url->MakeFocus(true); m_findGroup = layoutItemFor(findGroup); + m_tabGroup = layoutItemFor(m_tabManager->TabGroup()); } else { m_BackButton = 0; m_ForwardButton = 0; @@ -344,23 +343,28 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case CLOSE_TAB: { - if (m_tabView->CountTabs() > 1) - delete m_tabView->RemoveTab(m_tabView->Selection()); - else + case CLOSE_TAB: + if (m_tabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = m_tabManager->SelectedTabIndex(); + delete m_tabManager->RemoveTab(index); + updateTabGroupVisibility(); + } else PostMessage(B_QUIT_REQUESTED); break; - } case TAB_CHANGED: { // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index = -1; - message->FindInt32("index", &index); - BWebView* webView = dynamic_cast(m_tabView->ViewForTab(index)); + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + BWebView* webView = dynamic_cast(m_tabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + break; SetCurrentWebView(webView); - BTab* tab = m_tabView->TabAt(index); - if (tab) - updateTitle(tab->Label()); + if (webView) + updateTitle(webView->MainFrameTitle()); else updateTitle(""); if (webView) { @@ -384,8 +388,8 @@ bool LauncherWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. - while (m_tabView->CountTabs() > 0) - delete m_tabView->RemoveTab(0L); + while (m_tabManager->CountTabs() > 0) + delete m_tabManager->RemoveTab(0L); SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -432,21 +436,22 @@ void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) webView = new BWebView("web view"); webView->WebPage()->SetDownloadListener(m_downloadListener); - m_tabView->AddTab(webView); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - // TODO: Remove when BTabView is fixed... - m_tabView->Invalidate(); + m_tabManager->AddTab(webView, "New tab"); if (url.Length()) webView->LoadURL(url.String()); if (select) { - m_tabView->Select(m_tabView->CountTabs() - 1); + m_tabManager->SelectTab(m_tabManager->CountTabs() - 1); SetCurrentWebView(webView); NavigationCapabilitiesChanged(false, false, false, webView); - if (m_url) + if (m_url) { + m_url->SetText(url.String()); m_url->MakeFocus(true); + } } + + updateTabGroupVisibility(); } // #pragma mark - Notification API @@ -577,10 +582,9 @@ void LauncherWindow::SetResizable(bool flag, BWebView* view) void LauncherWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < m_tabView->CountTabs(); i++) { - if (m_tabView->ViewForTab(i) == view) { - m_tabView->TabAt(i)->SetLabel(title); - m_tabView->DrawTabs(); + for (int32 i = 0; i < m_tabManager->CountTabs(); i++) { + if (m_tabManager->ViewForTab(i) == view) { + m_tabManager->SetTabLabel(i, title); break; } } @@ -653,3 +657,11 @@ void LauncherWindow::updateTitle(const BString& title) windowTitle << "HaikuLauncher"; SetTitle(windowTitle.String()); } + +void LauncherWindow::updateTabGroupVisibility() +{ + if (Lock()) { + m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + Unlock(); + } +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 97b28f1123..e06837b48f 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -42,7 +42,7 @@ class BStatusBar; class BStringView; class BTextControl; class IconButton; -class WebTabView; +class TabManager; class BWebView; enum ToolbarPolicy { @@ -93,6 +93,7 @@ private: virtual void AuthenticationChallenge(BMessage* challenge); void updateTitle(const BString &title); + void updateTabGroupVisibility(); private: BMessenger m_downloadListener; @@ -106,9 +107,10 @@ private: BStringView* m_statusText; BStatusBar* m_loadingProgressBar; BLayoutItem* m_findGroup; + BLayoutItem* m_tabGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; - WebTabView* m_tabView; + TabManager* m_tabManager; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index b4ead81c6c..cb93ada686 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * @@ -27,34 +28,990 @@ #include "WebTabView.h" -#include +#include "WebView.h" +#include +#include +#include +#include +#include +#include +#include -WebTabView::WebTabView(const char *name, const BMessenger& target) - : BTabView(name) - , m_target(target) + +class TabView; +class TabContainerView; + + +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; + +private: + TabView* fParent; + BRect fFrame; +}; + + +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); + 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 TabContainerView : public BGroupView { +public: + class Controller { + public: + virtual void TabSelected(int32 tabIndex) = 0; + virtual bool HasFrames() = 0; + virtual TabView* CreateTabView() = 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); + + void AddTab(const char* label, int32 index = -1); + void AddTab(TabView* tab, int32 index = -1); + TabView* RemoveTab(int32 index); + + int32 IndexOf(TabView* tab) const; + + void SelectTab(int32 tabIndex); + void SelectTab(TabView* tab); + + void SetTabLabel(int32 tabIndex, const char* label); + +private: + TabView* _TabAt(const BPoint& where) const; + +private: + TabView* fLastMouseEventTab; + bool fMouseDown; + TabView* fSelectedTab; + Controller* fController; +}; + + +// #pragma mark - TabContainerView + + +static const float kLeftTabInset = 4; + + +TabContainerView::TabContainerView(Controller* controller) + : + BGroupView(B_HORIZONTAL), + fLastMouseEventTab(NULL), + fMouseDown(false), + fSelectedTab(NULL), + fController(controller) { - SetBorder(B_NO_BORDER); - SetFlags(Flags() & ~B_FULL_UPDATE_ON_RESIZE); + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); + GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); } -WebTabView::~WebTabView(void) + +TabContainerView::~TabContainerView() +{ + // TODO: Not so nice, that we take ownership of the controller. + delete fController; +} + + +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( + layout->ItemAt(i)); + if (!item) + 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) +{ + fMouseDown = true; + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + if (fLastMouseEventTab) + fLastMouseEventTab->MouseDown(where); +} + + +void +TabContainerView::MouseUp(BPoint where) +{ + fMouseDown = false; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseUp(where); +} + + +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 && 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); + } +} + + +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(GroupLayout()->ItemAt(index - 1)); + if (item) + item->Parent()->SetIsLast(false); + } +} + +TabView* +TabContainerView::RemoveTab(int32 index) +{ + TabLayoutItem* item + = dynamic_cast(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(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(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); + + return removedTab; +} + + +int32 +TabContainerView::IndexOf(TabView* tab) const +{ + return GroupLayout()->IndexOfItem(tab->LayoutItem()); +} + + +void +TabContainerView::SelectTab(int32 index) +{ + TabView* tab = NULL; + TabLayoutItem* item = dynamic_cast( + 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()); + + fController->TabSelected(index); + } +} + + +void +TabContainerView::SetTabLabel(int32 tabIndex, const char* label) +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(tabIndex)); + if (item == NULL) + return; + + item->Parent()->SetLabel(label); +} + + +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( + layout->ItemAt(i)); + if (item && item->Frame().Contains(where)) + return item->Parent(); + } + return NULL; +} + + +// #pragma mark - TabView + + +TabView::TabView() + : fContainerView(NULL) + , fLayoutItem(new TabLayoutItem(this)) + , fLabel() { } -void WebTabView::Select(int32 tab) +TabView::~TabView() { - BTabView::Select(tab); + // 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 = 100.0f; + return size; +} + +BSize TabView::PreferredSize() +{ + return MaxSize(); +} + +BSize TabView::MaxSize() +{ + float extra = be_control_look->DefaultLabelSpacing(); + float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; + labelWidth = min_c(300.0f, labelWidth); + 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) +{ + 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; + BRect frame = fLayoutItem->Frame(); + frame.bottom++; + fContainerView->Invalidate(frame); +} + +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) +{ +} + +bool TabLayoutItem::IsVisible() +{ + return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); +} + +void TabLayoutItem::SetVisible(bool visible) +{ + // not allowed +} + +BRect TabLayoutItem::Frame() +{ + return fFrame; +} + +void TabLayoutItem::SetFrame(BRect frame) +{ + BRect dirty = fFrame; + fFrame = frame; + dirty = dirty | fFrame; + // Invalidate more than necessary, to help the TabContainerView + // redraw the parts outside any tabs... + dirty.bottom++; + dirty.right++; + fParent->ContainerView()->Invalidate(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; +} + + +// #pragma mark - TabManagerController + + +class TabManagerController : public TabContainerView::Controller { +public: + TabManagerController(TabManager* manager); + + virtual void TabSelected(int32 index) + { + fManager->SelectTab(index); + } + + virtual bool HasFrames() + { + return false; + } + + virtual TabView* CreateTabView(); + + void CloseTab(int32 index); + +private: + TabManager* fManager; +}; + + +// #pragma mark - WebTabView + + +class WebTabView : public TabView { +public: + WebTabView(TabManagerController* controller); + + virtual BSize MaxSize(); + + virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + +private: + BRect _CloseRectFrame(BRect frame) const; + +private: + TabManagerController* fController; + bool fOverCloseRect; + bool fClicked; +}; + + +WebTabView::WebTabView(TabManagerController* controller) + : + TabView(), + fController(controller), + fOverCloseRect(false), + fClicked(false) +{ +} + + +BSize +WebTabView::MaxSize() +{ + // Account for close button. + BSize size(TabView::MaxSize()); + size.width += size.height; + return size; +} + + +void +WebTabView::DrawContents(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()) + tint *= 1.02; + + base = tint_color(base, tint); + + 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); + + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); +} + + +void +WebTabView::MouseDown(BPoint where) +{ + BRect closeRect = _CloseRectFrame(Frame()); + if (!closeRect.Contains(where)) { + TabView::MouseDown(where); + return; + } + + fClicked = true; + ContainerView()->Invalidate(closeRect); +} + + +void +WebTabView::MouseUp(BPoint where) +{ + if (!fClicked) { + TabView::MouseUp(where); + return; + } + + fClicked = false; + + if (_CloseRectFrame(Frame()).Contains(where)) + fController->CloseTab(ContainerView()->IndexOf(this)); +} + + +void +WebTabView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + BRect closeRect = _CloseRectFrame(Frame()); + bool overCloseRect = closeRect.Contains(where); + if (overCloseRect != fOverCloseRect) { + fOverCloseRect = overCloseRect; + ContainerView()->Invalidate(closeRect); + } + + TabView::MouseMoved(where, transit, dragMessage); +} + + +BRect +WebTabView::_CloseRectFrame(BRect frame) const +{ + frame.left = frame.right - frame.Height(); + return frame; +} + + +// #pragma mark - TabManagerController + + +TabManagerController::TabManagerController(TabManager* manager) + : + fManager(manager) +{ +} + + +TabView* +TabManagerController::CreateTabView() +{ + return new WebTabView(this); +} + + +void +TabManagerController::CloseTab(int32 index) +{ + fManager->CloseTab(index); +} + + +// #pragma mark - TabManager + + + +TabManager::TabManager(const BMessenger& target) + : + fTarget(target) +{ + fContainerView = new BView("web view container", 0); + fCardLayout = new BCardLayout(); + fContainerView->SetLayout(fCardLayout); + + fTabContainerView = new TabContainerView(new TabManagerController(this)); + fTabContainerGroup = new BGroupView(B_HORIZONTAL); + fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); + fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); +} + + +TabManager::~TabManager() +{ +} + + +void +TabManager::SetTarget(const BMessenger& target) +{ + fTarget = target; +} + + +const BMessenger& +TabManager::Target() const +{ + return fTarget; +} + + +BView* +TabManager::TabGroup() const +{ + return fTabContainerGroup; +} + + +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; +} + + +void +TabManager::SelectTab(int32 tabIndex) +{ + fCardLayout->SetVisibleItem(tabIndex); + fTabContainerView->SelectTab(tabIndex); + BMessage message(TAB_CHANGED); - message.AddInt32("index", tab); - m_target.SendMessage(&message); + message.AddInt32("tab index", tabIndex); + fTarget.SendMessage(&message); } -const BMessenger& WebTabView::target() const + +int32 +TabManager::SelectedTabIndex() const { - return m_target; + return fCardLayout->VisibleIndex(); } -void WebTabView::setTarget(const BMessenger& target) + +void +TabManager::CloseTab(int32 tabIndex) { - m_target = target; + 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); +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index ac85a460c1..c97c899c7b 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * @@ -25,28 +25,52 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebTabView_h -#define WebTabView_h +#ifndef TAB_MANAGER_H +#define TAB_MANAGER_H #include #include enum { - TAB_CHANGED = 'tcha' + TAB_CHANGED = 'tcha', + CLOSE_TAB = 'cltb' }; -class WebTabView : public BTabView { -public: - WebTabView(const char *name, const BMessenger& target); - virtual ~WebTabView(void); - virtual void Select(int32 tab); +class BCardLayout; +class BGroupView; +class TabContainerView; - const BMessenger& target() const; - void setTarget(const BMessenger& target); +class TabManager { +public: + TabManager(const BMessenger& target); + virtual ~TabManager(); + + void SetTarget(const BMessenger& target); + const BMessenger& Target() const; + + BView* TabGroup() const; + BView* ContainerView() const; + + BView* ViewForTab(int32 tabIndex) const; + + void SelectTab(int32 tabIndex); + 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); private: - BMessenger m_target; + BGroupView* fTabContainerGroup; + TabContainerView* fTabContainerView; + BView* fContainerView; + BCardLayout* fCardLayout; + + BMessenger fTarget; }; -#define WebTabView_h -#endif // WebTabView_h +#endif // TAB_MANAGER_H From 84c9928e4052b1cc0ee20d1b4dde9b2252422da6 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 23:17:51 +0000 Subject: [PATCH 064/293] * Added small symbol buttons to tab container view. Currently only "New tab" is added and works. * Added "Open location" shortcut Cmd-L as in Firefox. * Moved "Show downloads" shortcut to Cmd-J, again as in Firefox. It uses Cmd-D for "Bookmark this page". Though I have no idea why we simply shouldn't use Cmd-D for Downloads and Cmd-B for Bookmark this page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@229 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 24 ++-- src/apps/webpositive/WebTabView.cpp | 148 +++++++++++++++++++++++- src/apps/webpositive/WebTabView.h | 3 +- 3 files changed, 166 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 908c4a1582..4dac5a84b5 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -62,6 +62,7 @@ #include enum { + OPEN_LOCATION = 'open', GO_BACK = 'goba', GO_FORWARD = 'gofo', STOP = 'stop', @@ -95,7 +96,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { - m_tabManager = new TabManager(BMessenger(this)); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); + m_tabManager = new TabManager(BMessenger(this), newTabMessage); if (toolbarPolicy == HaveToolbar) { // Menu @@ -106,18 +111,15 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); menu->AddItem(newItem); newItem->SetTarget(be_app); - BMessage* newTabMessage = new BMessage(NEW_TAB); - newTabMessage->AddString("url", ""); - newTabMessage->AddPointer("window", this); - newTabMessage->AddBool("select", true); - newItem = new BMenuItem("New tab", newTabMessage, 'T'); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -253,6 +255,14 @@ LauncherWindow::~LauncherWindow() void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { + case OPEN_LOCATION: + if (m_url) { + if (m_url->TextView()->IsFocus()) + m_url->TextView()->SelectAll(); + else + m_url->MakeFocus(true); + } + break; case RELOAD: CurrentWebView()->LoadURL(m_url->Text()); break; diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index cb93ada686..5882c98de3 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -29,7 +29,9 @@ #include "WebTabView.h" #include "WebView.h" +#include #include +#include #include #include #include @@ -884,11 +886,149 @@ TabManagerController::CloseTab(int32 index) } +// #pragma mark - TabButton + + +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, + flags, 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) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); + } +}; + + +class ScrollRightTabButton : public TabButton { +public: + ScrollRightTabButton(BMessage* message) + : TabButton(message) + { + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); + } +}; + + +class NewTabButton : public TabButton { +public: + NewTabButton(BMessage* message) + : TabButton(message) + { + } + + 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); + } +}; + + // #pragma mark - TabManager -TabManager::TabManager(const BMessenger& target) +TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : fTarget(target) { @@ -900,6 +1040,12 @@ TabManager::TabManager(const BMessenger& target) fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); +// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); +// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); + NewTabButton* newTabButton = new NewTabButton(newTabMessage); + newTabButton->SetTarget(be_app); + fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); +// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); } diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index c97c899c7b..9df5f501c4 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -42,7 +42,8 @@ class TabContainerView; class TabManager { public: - TabManager(const BMessenger& target); + TabManager(const BMessenger& target, + BMessage* newTabMessage); virtual ~TabManager(); void SetTarget(const BMessenger& target); From f44756cf46a6c87ed142cf2a1c1d59981773ce13 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 00:05:33 +0000 Subject: [PATCH 065/293] Middle click anywhere into a tab closes that page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@230 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 5882c98de3..355290e6e0 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -84,7 +84,7 @@ public: virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void MouseDown(BPoint where); + virtual void MouseDown(BPoint where, uint32 buttons); virtual void MouseUp(BPoint where); virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); @@ -248,10 +248,13 @@ TabContainerView::Draw(BRect updateRect) void TabContainerView::MouseDown(BPoint where) { + uint32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) + buttons = B_PRIMARY_MOUSE_BUTTON; fMouseDown = true; SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); if (fLastMouseEventTab) - fLastMouseEventTab->MouseDown(where); + fLastMouseEventTab->MouseDown(where, buttons); } @@ -544,7 +547,7 @@ void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); } -void TabView::MouseDown(BPoint where) +void TabView::MouseDown(BPoint where, uint32 buttons) { fContainerView->SelectTab(this); } @@ -731,7 +734,7 @@ public: virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void MouseDown(BPoint where); + virtual void MouseDown(BPoint where, uint32 buttons); virtual void MouseUp(BPoint where); virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); @@ -811,11 +814,16 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, void -WebTabView::MouseDown(BPoint where) +WebTabView::MouseDown(BPoint where, uint32 buttons) { + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + fController->CloseTab(ContainerView()->IndexOf(this)); + return; + } + BRect closeRect = _CloseRectFrame(Frame()); if (!closeRect.Contains(where)) { - TabView::MouseDown(where); + TabView::MouseDown(where, buttons); return; } From 507875ecb1aabbbaf57bd52681637647253151f8 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 27 Feb 2010 01:48:18 +0000 Subject: [PATCH 066/293] Add Cmd+R as a shortcut for reload page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@231 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4dac5a84b5..d3589820c3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -244,7 +244,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - + AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + be_app->PostMessage(WINDOW_OPENED); } From 1cba0fd63a2a0442a6e41d15e2c2a24aa49c3e17 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 11:01:36 +0000 Subject: [PATCH 067/293] * Use the proper channels for reloading. (Added BWebView/BWebPage::Reload().) * Catch B_RETURN key down messages, when the target is the URL text view. Don't let the text view send a message, but react on B_RETURN only, in the window, also letting the Go button flash for a bonus. This fixes unprovoked (re-)loading of pages when the text control went out of focus and thought the text had changed, sending GOTO_URL. This could happen when just grabbing the scrollbar so that the text control looses focus. Also makes the m_loadedURL string superfluous, which I added for the same purpose. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@232 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 42 ++++++++++++++++++------- src/apps/webpositive/LauncherWindow.h | 3 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d3589820c3..d2c77647ae 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -151,11 +151,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_StopButton->TrimIcon(); // URL - m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); + m_url = new BTextControl("url", "", "", NULL); m_url->SetDivider(50.0); // Go - BButton* button = new BButton("", "Go", new BMessage(RELOAD)); + m_goButton = new BButton("", "Go", new BMessage(GOTO_URL)); // Status Bar m_statusText = new BStringView("status", ""); @@ -201,7 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(m_ForwardButton, 1, 0) .Add(m_StopButton, 2, 0) .Add(m_url, 3, 0) - .Add(button, 4, 0) + .Add(m_goButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -223,6 +223,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } else { m_BackButton = 0; m_ForwardButton = 0; + m_StopButton = 0; + m_goButton = 0; m_url = 0; m_menuBar = 0; m_statusText = 0; @@ -253,6 +255,27 @@ LauncherWindow::~LauncherWindow() { } +void LauncherWindow::DispatchMessage(BMessage* message, BHandler* target) +{ + if (m_url && message->what == B_KEY_DOWN && target == m_url->TextView()) { + // Handle B_RETURN in the URL text control. This is the easiest + // way to react *only* when the user presses the return key in the + // address bar, as opposed to trying to load whatever is in there when + // the text control just goes out of focus. + const char* bytes; + if (message->FindString("bytes", &bytes) == B_OK + && bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + m_goButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + m_goButton->Invoke(); + snooze(1000); + m_goButton->SetValue(B_CONTROL_OFF); + } + } + BWebWindow::DispatchMessage(message, target); +} + void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { @@ -265,13 +288,13 @@ void LauncherWindow::MessageReceived(BMessage* message) } break; case RELOAD: - CurrentWebView()->LoadURL(m_url->Text()); + CurrentWebView()->Reload(); break; case GOTO_URL: { - BString url = m_url->Text(); - message->FindString("url", &url); - if (m_loadedURL != url) - CurrentWebView()->LoadURL(url.String()); + BString url; + if (message->FindString("url", &url) != B_OK) + url = m_url->Text(); + CurrentWebView()->LoadURL(url.String()); break; } case GO_BACK: @@ -502,8 +525,6 @@ void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) if (view != CurrentWebView()) return; - m_loadedURL = url; - // This hook is invoked when the load is commited. if (m_url) m_url->SetText(url.String()); @@ -542,7 +563,6 @@ void LauncherWindow::LoadFinished(const BString& url, BWebView* view) if (view != CurrentWebView()) return; - m_loadedURL = url; BString status(url); status << " finished."; StatusChanged(status, view); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e06837b48f..192d42786a 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -64,6 +64,7 @@ public: ToolbarPolicy = HaveToolbar); virtual ~LauncherWindow(); + virtual void DispatchMessage(BMessage* message, BHandler* target); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); @@ -102,8 +103,8 @@ private: IconButton* m_BackButton; IconButton* m_ForwardButton; IconButton* m_StopButton; + BButton* m_goButton; BTextControl* m_url; - BString m_loadedURL; BStringView* m_statusText; BStatusBar* m_loadingProgressBar; BLayoutItem* m_findGroup; From bf0181bd0014d91717a12af6af7b9da78c21db73 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 12:26:17 +0000 Subject: [PATCH 068/293] Instead of hiding the tab view when there is only one tab, make the tab close buttons only available when there is more than one tab. This gives a more consistent interface and doesn't hide features, most importantly the "Add tab" button. For users that wish the most minimalistic UI, this behavior could later be configurable (along with opening new windows versus new tabs). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@233 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 +- src/apps/webpositive/WebTabView.cpp | 160 ++++++++++++++---------- src/apps/webpositive/WebTabView.h | 3 + 3 files changed, 102 insertions(+), 64 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d2c77647ae..4bd0ac61a6 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -692,7 +692,8 @@ void LauncherWindow::updateTitle(const BString& title) void LauncherWindow::updateTabGroupVisibility() { if (Lock()) { - m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + //m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + m_tabManager->SetCloseButtonsAvailable(m_tabManager->CountTabs() > 1); Unlock(); } } diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 355290e6e0..483f5b2811 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -187,8 +187,6 @@ TabContainerView::TabContainerView(Controller* controller) TabContainerView::~TabContainerView() { - // TODO: Not so nice, that we take ownership of the controller. - delete fController; } @@ -717,8 +715,19 @@ public: void CloseTab(int32 index); + void SetCloseButtonsAvailable(bool available) + { + fCloseButtonsAvailable = available; + } + + bool CloseButtonsAvailable() const + { + return fCloseButtonsAvailable; + } + private: TabManager* fManager; + bool fCloseButtonsAvailable; }; @@ -740,6 +749,8 @@ public: const BMessage* dragMessage); private: + void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront); BRect _CloseRectFrame(BRect frame) const; private: @@ -772,6 +783,75 @@ WebTabView::MaxSize() 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); + + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); +} + + +void +WebTabView::MouseDown(BPoint where, uint32 buttons) +{ + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + fController->CloseTab(ContainerView()->IndexOf(this)); + 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) { + TabView::MouseUp(where); + return; + } + + fClicked = 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); + } + } + + TabView::MouseMoved(where, transit, dragMessage); +} + + +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(); @@ -808,65 +888,6 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom()); owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop()); owner->SetPenSize(1); - - TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); -} - - -void -WebTabView::MouseDown(BPoint where, uint32 buttons) -{ - if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); - return; - } - - BRect closeRect = _CloseRectFrame(Frame()); - if (!closeRect.Contains(where)) { - TabView::MouseDown(where, buttons); - return; - } - - fClicked = true; - ContainerView()->Invalidate(closeRect); -} - - -void -WebTabView::MouseUp(BPoint where) -{ - if (!fClicked) { - TabView::MouseUp(where); - return; - } - - fClicked = false; - - if (_CloseRectFrame(Frame()).Contains(where)) - fController->CloseTab(ContainerView()->IndexOf(this)); -} - - -void -WebTabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - BRect closeRect = _CloseRectFrame(Frame()); - bool overCloseRect = closeRect.Contains(where); - if (overCloseRect != fOverCloseRect) { - fOverCloseRect = overCloseRect; - ContainerView()->Invalidate(closeRect); - } - - TabView::MouseMoved(where, transit, dragMessage); -} - - -BRect -WebTabView::_CloseRectFrame(BRect frame) const -{ - frame.left = frame.right - frame.Height(); - return frame; } @@ -875,7 +896,8 @@ WebTabView::_CloseRectFrame(BRect frame) const TabManagerController::TabManagerController(TabManager* manager) : - fManager(manager) + fManager(manager), + fCloseButtonsAvailable(false) { } @@ -1038,13 +1060,14 @@ public: TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : + fController(new TabManagerController(this)), fTarget(target) { fContainerView = new BView("web view container", 0); fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); - fTabContainerView = new TabContainerView(new TabManagerController(this)); + fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); @@ -1059,6 +1082,7 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) TabManager::~TabManager() { + delete fController; } @@ -1169,3 +1193,13 @@ TabManager::SetTabLabel(int32 tabIndex, const char* label) fTabContainerView->SetTabLabel(tabIndex, label); } + +void +TabManager::SetCloseButtonsAvailable(bool available) +{ + if (available == fController->CloseButtonsAvailable()) + return; + fController->SetCloseButtonsAvailable(available); + fTabContainerView->Invalidate(); +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 9df5f501c4..9965e62a9a 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -39,6 +39,7 @@ enum { class BCardLayout; class BGroupView; class TabContainerView; +class TabManagerController; class TabManager { public: @@ -64,12 +65,14 @@ public: int32 CountTabs() const; void SetTabLabel(int32 tabIndex, const char* label); + void SetCloseButtonsAvailable(bool available); private: BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; BCardLayout* fCardLayout; + TabManagerController* fController; BMessenger fTarget; }; From b3a723711e7a9145ea9cd4e9ba6916a510bb1eac Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:09:57 +0000 Subject: [PATCH 069/293] Added tool tip to Add tab button... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@234 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 483f5b2811..e635c03cc8 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1010,6 +1010,7 @@ public: NewTabButton(BMessage* message) : TabButton(message) { + SetToolTip("New tab (Cmd-T)"); } virtual BSize MinSize() From ce1641f62c58ef2dd82e37b96f3b35071cef2468 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:20:24 +0000 Subject: [PATCH 070/293] Hide the implementation details of BWebWindow::AuthenticationChallenge() from clients. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@235 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 29 +++++-------------------- src/apps/webpositive/LauncherWindow.h | 4 +++- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4bd0ac61a6..e44836cec8 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -653,31 +653,14 @@ void LauncherWindow::UpdateGlobalHistory(const BString& url) BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -void LauncherWindow::AuthenticationChallenge(BMessage* message) +bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, + BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount) { - BString text; - bool rememberCredentials = false; - uint32 failureCount = 0; - BString user; - BString password; - - message->FindString("text", &text); - message->FindString("user", &user); - message->FindString("password", &password); - message->FindUInt32("failureCount", &failureCount); - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - if (!panel->getAuthentication(text, user, password, rememberCredentials, - failureCount > 0, user, password, &rememberCredentials)) { - message->SendReply((uint32)0); - return; - } - - BMessage reply; - reply.AddString("user", user); - reply.AddString("password", password); - reply.AddBool("rememberCredentials", rememberCredentials); - message->SendReply(&reply); + // Panel auto-destructs. + return panel->getAuthentication(message, inOutUser, inOutPassword, + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } void LauncherWindow::updateTitle(const BString& title) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 192d42786a..e502360f49 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -91,7 +91,9 @@ private: virtual void NavigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, BWebView* view); virtual void UpdateGlobalHistory(const BString& url); - virtual void AuthenticationChallenge(BMessage* challenge); + virtual bool AuthenticationChallenge(BString message, BString& inOutUser, + BString& inOutPassword, bool& inOutRememberCredentials, + uint32 failureCount); void updateTitle(const BString &title); void updateTabGroupVisibility(); From 3d6558b6ca6f25e225951fec74e144001e911678 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:20:50 +0000 Subject: [PATCH 071/293] Coding style fix. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@236 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e44836cec8..63ace8ba70 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -659,8 +659,8 @@ bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. return panel->getAuthentication(message, inOutUser, inOutPassword, - inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, - &inOutRememberCredentials); + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } void LauncherWindow::updateTitle(const BString& title) From 50c04c441db77a54512b0eff6f6e3323fe403f46 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:31:29 +0000 Subject: [PATCH 072/293] Actually, the authentication challenge needs to know for which page it is, otherwise we may display the login panel above an unrelated page. Tested by clicking Login on dev.haiku-os.org and Cmd-T to open a new tab before the login panel shows. Works. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@237 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 8 +++++++- src/apps/webpositive/LauncherWindow.h | 2 +- src/apps/webpositive/WebTabView.cpp | 14 ++++++++++++++ src/apps/webpositive/WebTabView.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 63ace8ba70..37ff504ae6 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -654,8 +654,14 @@ void LauncherWindow::UpdateGlobalHistory(const BString& url) } bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, - BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount) + BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, + BWebView* view) { + // Switch to the page for which this authentication is required. + if (view != CurrentWebView()) { + m_tabManager->SelectTab(view); + UpdateIfNeeded(); + } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. return panel->getAuthentication(message, inOutUser, inOutPassword, diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e502360f49..018ac29a16 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -93,7 +93,7 @@ private: virtual void UpdateGlobalHistory(const BString& url); virtual bool AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, - uint32 failureCount); + uint32 failureCount, BWebView* view); void updateTitle(const BString &title); void updateTabGroupVisibility(); diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index e635c03cc8..1b491385c0 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1137,6 +1137,20 @@ TabManager::SelectTab(int32 tabIndex) } +void +TabManager::SelectTab(BView* containedView) +{ + int32 count = fCardLayout->CountItems(); + for (int32 i = 0; i < count; i++) { + BLayoutItem* item = fCardLayout->ItemAt(i); + if (item->View() == containedView) { + SelectTab(i); + break; + } + } +} + + int32 TabManager::SelectedTabIndex() const { diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 9965e62a9a..3f9f086755 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -56,6 +56,7 @@ public: BView* ViewForTab(int32 tabIndex) const; void SelectTab(int32 tabIndex); + void SelectTab(BView* containedView); int32 SelectedTabIndex() const; void CloseTab(int32 tabIndex); From 0b355b4e977e1c28512c3c60b9fb143e7a574ea1 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 14:58:51 +0200 Subject: [PATCH 073/293] Rename LauncherXXX files to their new WebPositive names Edit history with this rename commit to preserve history as we will git-filter --subdirectory-filter the WebPositive directory. The HaikuLauncher directory was renamed to WebPositive trough the past history with git-filter. --- src/apps/webpositive/{LauncherApp.cpp => BrowserApp.cpp} | 0 src/apps/webpositive/{LauncherApp.h => BrowserApp.h} | 0 src/apps/webpositive/{LauncherWindow.cpp => BrowserWindow.cpp} | 0 src/apps/webpositive/{LauncherWindow.h => BrowserWindow.h} | 0 src/apps/webpositive/{Launcher.rdef => WebPositive.rdef} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/apps/webpositive/{LauncherApp.cpp => BrowserApp.cpp} (100%) rename src/apps/webpositive/{LauncherApp.h => BrowserApp.h} (100%) rename src/apps/webpositive/{LauncherWindow.cpp => BrowserWindow.cpp} (100%) rename src/apps/webpositive/{LauncherWindow.h => BrowserWindow.h} (100%) rename src/apps/webpositive/{Launcher.rdef => WebPositive.rdef} (100%) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/BrowserApp.cpp similarity index 100% rename from src/apps/webpositive/LauncherApp.cpp rename to src/apps/webpositive/BrowserApp.cpp diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/BrowserApp.h similarity index 100% rename from src/apps/webpositive/LauncherApp.h rename to src/apps/webpositive/BrowserApp.h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp similarity index 100% rename from src/apps/webpositive/LauncherWindow.cpp rename to src/apps/webpositive/BrowserWindow.cpp diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/BrowserWindow.h similarity index 100% rename from src/apps/webpositive/LauncherWindow.h rename to src/apps/webpositive/BrowserWindow.h diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/WebPositive.rdef similarity index 100% rename from src/apps/webpositive/Launcher.rdef rename to src/apps/webpositive/WebPositive.rdef From a3b3ded520bdf755cef087bfdb2323c0a832627d Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 15:05:29 +0200 Subject: [PATCH 074/293] Manually update to the r238 state, so that we can rebase next commits on top of it Original commit message of r238: Split up WebPositive from HaikuLauncher. HaikuLauncher is back to it's simple self. WebPositive uses a new WebPositive folder in config/settings. Otherwise, everything should be as before. LauncherWindow and LauncherApp have been renamed and cleaned up for the Haiku coding style. --- src/apps/webpositive/BrowserApp.cpp | 351 ++++---- src/apps/webpositive/BrowserApp.h | 54 +- src/apps/webpositive/BrowserWindow.cpp | 997 ++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 134 +-- src/apps/webpositive/BrowsingHistory.cpp | 4 +- src/apps/webpositive/DownloadWindow.cpp | 4 +- src/apps/webpositive/WebPositive.rdef | 6 +- 7 files changed, 833 insertions(+), 717 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 5ebef34120..3dd0d7a25a 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -8,10 +8,10 @@ * 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. + * 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. + * 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 @@ -27,17 +27,16 @@ */ #include "config.h" -#include "LauncherApp.h" +#include "BrowserApp.h" +#include "BrowserWindow.h" #include "DownloadWindow.h" -#include "FrameView.h" -#include "GraphicsContext.h" -#include "LauncherWindow.h" #include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include #include +#include #include #include #include @@ -45,170 +44,187 @@ #include #include -extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; + +const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; +const char* kApplicationName = "WebPositive"; + + enum { - LOAD_AT_STARTING = 'lost' + LOAD_AT_STARTING = 'lost' }; -LauncherApp::LauncherApp() - : BApplication(kApplicationSignature) - , m_windowCount(0) - , m_lastWindowFrame(100, 100, 700, 750) - , m_launchRefsMessage(0) - , m_initialized(false) - , m_downloadWindow(0) +BrowserApp::BrowserApp() + : BApplication(kApplicationSignature) + , fWindowCount(0) + , fLastWindowFrame(100, 100, 700, 750) + , fLaunchRefsMessage(0) + , fInitialized(false) + , fDownloadWindow(0) { } -LauncherApp::~LauncherApp() + +BrowserApp::~BrowserApp() { - delete m_launchRefsMessage; + delete fLaunchRefsMessage; } -void LauncherApp::AboutRequested() + +void +BrowserApp::AboutRequested() { - BAlert* alert = new BAlert("About HaikuLauncher", - "For testing WebKit...\n\nby Ryan Leavengood", "Sweet!"); - alert->Go(); + BAlert* alert = new BAlert("About WebPositive", + "WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " + "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus", + "Sweet!"); + alert->Go(); } -void LauncherApp::ArgvReceived(int32 argc, char** argv) + +void +BrowserApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { const char* url = argv[i]; BEntry entry(argv[i], true); BPath path; if (entry.Exists() && entry.GetPath(&path) == B_OK) - url = path.Path(); - BMessage message(LOAD_AT_STARTING); - message.AddString("url", url); - message.AddBool("new window", m_initialized || i > 1); - PostMessage(&message); + url = path.Path(); + BMessage message(LOAD_AT_STARTING); + message.AddString("url", url); + message.AddBool("new window", fInitialized || i > 1); + PostMessage(&message); } } -void LauncherApp::ReadyToRun() + +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); + BWebPage::InitializeOnce(); + BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; - BRect windowFrameFromSettings = m_lastWindowFrame; + BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); bool showDownloads = false; - if (openSettingsFile(settingsFile, B_READ_ONLY)) { + if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); settingsArchive.FindRect("window frame", &windowFrameFromSettings); settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); settingsArchive.FindBool("show downloads", &showDownloads); } - m_lastWindowFrame = windowFrameFromSettings; + fLastWindowFrame = windowFrameFromSettings; - m_downloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); - m_initialized = true; + fInitialized = true; - if (m_launchRefsMessage) { - RefsReceived(m_launchRefsMessage); - delete m_launchRefsMessage; - m_launchRefsMessage = 0; + if (fLaunchRefsMessage) { + RefsReceived(fLaunchRefsMessage); + delete fLaunchRefsMessage; + fLaunchRefsMessage = 0; } else { - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, - BMessenger(m_downloadWindow)); - window->Show(); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, + BMessenger(fDownloadWindow)); + window->Show(); } } -void LauncherApp::MessageReceived(BMessage* message) + +void +BrowserApp::MessageReceived(BMessage* message) { - switch (message->what) { - case LOAD_AT_STARTING: { - BString url; - if (message->FindString("url", &url) != B_OK) - break; - bool openNewWindow = false; - message->FindBool("new window", &openNewWindow); - LauncherWindow* webWindow = NULL; - for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!openNewWindow) { - // stop at the first window - break; - } - } - if (webWindow) { - // There should always be at least one window open. If not, maybe we are about - // to quit anyway... - if (openNewWindow) { - // open a new window with an offset to the last window - newWindow(url); - } else { - // load the URL in the first window - webWindow->CurrentWebView()->LoadURL(url.String()); - } - } - break; - } - case B_SILENT_RELAUNCH: - newWindow(""); - break; - case NEW_WINDOW: { + switch (message->what) { + case LOAD_AT_STARTING: { BString url; if (message->FindString("url", &url) != B_OK) break; - newWindow(url); - break; - } - case NEW_TAB: { - LauncherWindow* window; + bool openNewWindow = false; + message->FindBool("new window", &openNewWindow); + BrowserWindow* webWindow = NULL; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!openNewWindow) { + // stop at the first window + break; + } + } + if (webWindow) { + // There should always be at least one window open. If not, maybe we are about + // to quit anyway... + if (openNewWindow) { + // open a new window with an offset to the last window + _CreateNewWindow(url); + } else { + // load the URL in the first window + webWindow->CurrentWebView()->LoadURL(url.String()); + } + } + break; + } + case B_SILENT_RELAUNCH: + _CreateNewWindow(""); + 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(&window)) != B_OK) break; - BString url; + BString url; message->FindString("url", &url); - bool select = false; + bool select = false; message->FindBool("select", &select); - newTab(window, url, select); - break; - } - case WINDOW_OPENED: - m_windowCount++; - break; - case WINDOW_CLOSED: - m_windowCount--; - message->FindRect("window frame", &m_lastWindowFrame); - if (m_windowCount <= 0) - PostMessage(B_QUIT_REQUESTED); - break; + _CreateNewTab(window, url, select); + break; + } + case WINDOW_OPENED: + fWindowCount++; + break; + case WINDOW_CLOSED: + fWindowCount--; + message->FindRect("window frame", &fLastWindowFrame); + if (fWindowCount <= 0) + PostMessage(B_QUIT_REQUESTED); + break; - case SHOW_DOWNLOAD_WINDOW: { - BAutolock _(m_downloadWindow); - uint32 workspaces; - if (message->FindUInt32("workspaces", &workspaces) == B_OK) - m_downloadWindow->SetWorkspaces(workspaces); - if (m_downloadWindow->IsHidden()) - m_downloadWindow->Show(); - else - m_downloadWindow->Activate(); - } + case SHOW_DOWNLOAD_WINDOW: { + BAutolock _(fDownloadWindow); + uint32 workspaces; + if (message->FindUInt32("workspaces", &workspaces) == B_OK) + fDownloadWindow->SetWorkspaces(workspaces); + if (fDownloadWindow->IsHidden()) + fDownloadWindow->Show(); + else + fDownloadWindow->Activate(); + } - default: - BApplication::MessageReceived(message); - break; - } + default: + BApplication::MessageReceived(message); + break; + } } -void LauncherApp::RefsReceived(BMessage* message) + +void +BrowserApp::RefsReceived(BMessage* message) { - if (!m_initialized) { - delete m_launchRefsMessage; - m_launchRefsMessage = new BMessage(*message); + if (!fInitialized) { + delete fLaunchRefsMessage; + fLaunchRefsMessage = new BMessage(*message); return; } @@ -222,82 +238,97 @@ void LauncherApp::RefsReceived(BMessage* message) continue; BString url; url << path.Path(); - newWindow(url); + _CreateNewWindow(url); } } -bool LauncherApp::QuitRequested() + +bool +BrowserApp::QuitRequested() { - for (int i = 0; BWindow* window = WindowAt(i); i++) { - LauncherWindow* webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!webWindow->Lock()) - continue; - if (webWindow->QuitRequested()) { - m_lastWindowFrame = webWindow->Frame(); - webWindow->Quit(); - i--; - } else { - webWindow->Unlock(); - return false; - } - } + for (int i = 0; BWindow* window = WindowAt(i); i++) { + BrowserWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!webWindow->Lock()) + continue; + if (webWindow->QuitRequested()) { + fLastWindowFrame = webWindow->Frame(); + webWindow->Quit(); + i--; + } else { + webWindow->Unlock(); + return false; + } + } BFile settingsFile; - if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + if (_OpenSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; - settingsArchive.AddRect("window frame", m_lastWindowFrame); - if (m_downloadWindow->Lock()) { - settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !m_downloadWindow->IsHidden()); - m_downloadWindow->Unlock(); + settingsArchive.AddRect("window frame", fLastWindowFrame); + if (fDownloadWindow->Lock()) { + settingsArchive.AddRect("downloads window frame", fDownloadWindow->Frame()); + settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); + fDownloadWindow->Unlock(); } settingsArchive.Flatten(&settingsFile); } - return true; + return true; } -bool LauncherApp::openSettingsFile(BFile& file, uint32 mode) + +bool +BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher") != B_OK) { + || path.Append(kApplicationName) != B_OK + || create_directory(path.Path(), 0777) != B_OK + || path.Append("Application") != B_OK) { return false; } + return file.SetTo(path.Path(), mode) == B_OK; } -void LauncherApp::newWindow(const BString& url) -{ - m_lastWindowFrame.OffsetBy(20, 20); - if (!BScreen().Frame().Contains(m_lastWindowFrame)) - m_lastWindowFrame.OffsetTo(50, 50); - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, - BMessenger(m_downloadWindow)); +void +BrowserApp::_CreateNewWindow(const BString& url) +{ + fLastWindowFrame.OffsetBy(20, 20); + if (!BScreen().Frame().Contains(fLastWindowFrame)) + fLastWindowFrame.OffsetTo(50, 50); + + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, + BMessenger(fDownloadWindow)); window->Show(); if (url.Length()) - window->CurrentWebView()->LoadURL(url.String()); + window->CurrentWebView()->LoadURL(url.String()); } -void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) + +void +BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, + bool select) { - if (!window->Lock()) - return; - window->newTab(url, select); - window->Unlock(); + if (!window->Lock()) + return; + window->CreateNewTab(url, select); + window->Unlock(); } + // #pragma mark - -int main(int, char**) -{ - new LauncherApp(); - be_app->Run(); - delete be_app; - return 0; +int +main(int, char**) +{ + new BrowserApp(); + be_app->Run(); + delete be_app; + + return 0; } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 15dabba6a2..f834d41f62 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -8,10 +8,10 @@ * 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. + * 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. + * 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 @@ -25,43 +25,49 @@ * (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 -#ifndef LauncherApp_h -#define LauncherApp_h #include #include class BFile; class DownloadWindow; -class LauncherWindow; +class BrowserWindow; -class LauncherApp : public BApplication { + +class BrowserApp : public BApplication { public: - LauncherApp(); - virtual ~LauncherApp(); + BrowserApp(); + virtual ~BrowserApp(); - virtual void AboutRequested(); - virtual void ArgvReceived(int32, char**); - virtual void MessageReceived(BMessage*); - virtual void RefsReceived(BMessage*); - virtual void ReadyToRun(); - virtual bool QuitRequested(); + 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: - bool openSettingsFile(BFile& file, uint32 mode); - void newWindow(const BString& url); - void newTab(LauncherWindow* window, const BString& url, bool select); + bool _OpenSettingsFile(BFile& file, uint32 mode); + void _CreateNewWindow(const BString& url); + void _CreateNewTab(BrowserWindow* window, + const BString& url, bool select); - int m_windowCount; - BRect m_lastWindowFrame; - BMessage* m_launchRefsMessage; - bool m_initialized; +private: + int fWindowCount; + BRect fLastWindowFrame; + BMessage* fLaunchRefsMessage; + bool fInitialized; - DownloadWindow* m_downloadWindow; + DownloadWindow* fDownloadWindow; }; + extern const char* kApplicationSignature; +extern const char* kApplicationName; -#endif // LauncherApp_h + +#endif // BROWSER_APP_H diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 37ff504ae6..ee11bf91ac 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -31,12 +31,12 @@ */ #include "config.h" -#include "LauncherWindow.h" +#include "BrowserWindow.h" #include "AuthenticationPanel.h" +#include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" -#include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -61,628 +61,687 @@ #include + enum { OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', - TEXT_SHOW_FIND_GROUP = 'sfnd', - TEXT_HIDE_FIND_GROUP = 'hfnd', - TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp', + TEXT_SHOW_FIND_GROUP = 'sfnd', + TEXT_HIDE_FIND_GROUP = 'hfnd', + TEXT_FIND_NEXT = 'fndn', + TEXT_FIND_PREVIOUS = 'fndp', }; -using namespace WebCore; -static BLayoutItem* layoutItemFor(BView* view) +static BLayoutItem* +layoutItemFor(BView* view) { - BLayout* layout = view->Parent()->GetLayout(); - int32 index = layout->IndexOfView(view); - return layout->ItemAt(index); + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); } -LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy toolbarPolicy) - : BWebWindow(frame, "HaikuLauncher", - B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) - , m_downloadListener(downloadListener) + +BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy toolbarPolicy) + : BWebWindow(frame, kApplicationName, + B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + , fDownloadListener(downloadListener) { - BMessage* newTabMessage = new BMessage(NEW_TAB); - newTabMessage->AddString("url", ""); - newTabMessage->AddPointer("window", this); - newTabMessage->AddBool("select", true); - m_tabManager = new TabManager(BMessenger(this), newTabMessage); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); + fTabManager = new TabManager(BMessenger(this), newTabMessage); - if (toolbarPolicy == HaveToolbar) { - // Menu - m_menuBar = new BMenuBar("Main menu"); - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - m_menuBar->AddItem(menu); + if (toolbarPolicy == HaveToolbar) { + // Menu + fMenuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + fMenuBar->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - m_menuBar->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + fMenuBar->AddItem(menu); - m_goMenu = new BMenu("Go"); - m_menuBar->AddItem(m_goMenu); + fGoMenu = new BMenu("Go"); + fMenuBar->AddItem(fGoMenu); - // Back, Forward & Stop - m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); - m_BackButton->SetIcon(201); - m_BackButton->TrimIcon(); + // Back, Forward & Stop + fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + fBackButton->SetIcon(201); + fBackButton->TrimIcon(); - m_ForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); - m_ForwardButton->SetIcon(202); - m_ForwardButton->TrimIcon(); + fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + fForwardButton->SetIcon(202); + fForwardButton->TrimIcon(); - m_StopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); - m_StopButton->SetIcon(204); - m_StopButton->TrimIcon(); + fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + fStopButton->SetIcon(204); + fStopButton->TrimIcon(); - // URL - m_url = new BTextControl("url", "", "", NULL); - m_url->SetDivider(50.0); + // URL + fURLTextControl = new BTextControl("url", "", "", NULL); + fURLTextControl->SetDivider(50.0); - // Go - m_goButton = new BButton("", "Go", new BMessage(GOTO_URL)); + // Go + fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); - // Status Bar - m_statusText = new BStringView("status", ""); - m_statusText->SetAlignment(B_ALIGN_LEFT); - m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 12)); - // Prevent the window from growing to fit a long status message... - BFont font(be_plain_font); - font.SetSize(ceilf(font.Size() * 0.8)); - m_statusText->SetFont(&font, B_FONT_SIZE); + // Status Bar + fStatusText = new BStringView("status", ""); + fStatusText->SetAlignment(B_ALIGN_LEFT); + fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + fStatusText->SetExplicitMinSize(BSize(150, 12)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + fStatusText->SetFont(&font, B_FONT_SIZE); - // Loading progress bar - m_loadingProgressBar = new BStatusBar("progress"); - m_loadingProgressBar->SetMaxValue(100); - m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(12); + // Loading progress bar + fLoadingProgressBar = new BStatusBar("progress"); + fLoadingProgressBar->SetMaxValue(100); + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetBarHeight(12); - const float kInsetSpacing = 5; - const float kElementSpacing = 7; + const float kInsetSpacing = 5; + const float kElementSpacing = 7; - m_findTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); - m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(m_findTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) - .Add(m_findCaseSensitiveCheckBox) - .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) - .SetInsets(kInsetSpacing, kInsetSpacing, - kInsetSpacing, kInsetSpacing) - ) - ; - // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(m_menuBar) - .Add(m_tabManager->TabGroup()) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(m_BackButton, 0, 0) - .Add(m_ForwardButton, 1, 0) - .Add(m_StopButton, 2, 0) - .Add(m_url, 3, 0) - .Add(m_goButton, 4, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(m_tabManager->ContainerView()) - .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(m_statusText) - .Add(m_loadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) - ) - ); + fFindTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fFindTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(fFindCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(fMenuBar) + .Add(fTabManager->TabGroup()) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(fBackButton, 0, 0) + .Add(fForwardButton, 1, 0) + .Add(fStopButton, 2, 0) + .Add(fURLTextControl, 3, 0) + .Add(fGoButton, 4, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(fTabManager->ContainerView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) + ); - m_url->MakeFocus(true); + fURLTextControl->MakeFocus(true); - m_findGroup = layoutItemFor(findGroup); - m_tabGroup = layoutItemFor(m_tabManager->TabGroup()); - } else { - m_BackButton = 0; - m_ForwardButton = 0; - m_StopButton = 0; - m_goButton = 0; - m_url = 0; - m_menuBar = 0; - m_statusText = 0; - m_loadingProgressBar = 0; + fFindGroup = layoutItemFor(findGroup); + fTabGroup = layoutItemFor(fTabManager->TabGroup()); + } else { + fBackButton = 0; + fForwardButton = 0; + fStopButton = 0; + fGoButton = 0; + fURLTextControl = 0; + fMenuBar = 0; + fStatusText = 0; + fLoadingProgressBar = 0; - BWebView* webView = new BWebView("web_view"); - SetCurrentWebView(webView); + BWebView* webView = new BWebView("web_view"); + SetCurrentWebView(webView); - AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(CurrentWebView()) - ); - } + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) + .Add(CurrentWebView()) + ); + } - newTab("", true); + CreateNewTab("", true); - m_findGroup->SetVisible(false); + fFindGroup->SetVisible(false); - AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); - AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); - AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); + AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); + AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); - be_app->PostMessage(WINDOW_OPENED); + be_app->PostMessage(WINDOW_OPENED); } -LauncherWindow::~LauncherWindow() + +BrowserWindow::~BrowserWindow() { } -void LauncherWindow::DispatchMessage(BMessage* message, BHandler* target) + +void +BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { - if (m_url && message->what == B_KEY_DOWN && target == m_url->TextView()) { + if (fURLTextControl && message->what == B_KEY_DOWN + && target == fURLTextControl->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there when // the text control just goes out of focus. - const char* bytes; - if (message->FindString("bytes", &bytes) == B_OK - && bytes[0] == B_RETURN) { - // Do it in such a way that the user sees the Go-button go down. - m_goButton->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - m_goButton->Invoke(); - snooze(1000); - m_goButton->SetValue(B_CONTROL_OFF); - } + const char* bytes; + if (message->FindString("bytes", &bytes) == B_OK + && bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + fGoButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + fGoButton->Invoke(); + snooze(1000); + fGoButton->SetValue(B_CONTROL_OFF); + } } BWebWindow::DispatchMessage(message, target); } -void LauncherWindow::MessageReceived(BMessage* message) + +void +BrowserWindow::MessageReceived(BMessage* message) { - switch (message->what) { - case OPEN_LOCATION: - if (m_url) { - if (m_url->TextView()->IsFocus()) - m_url->TextView()->SelectAll(); - else - m_url->MakeFocus(true); - } - break; - case RELOAD: - CurrentWebView()->Reload(); - break; - case GOTO_URL: { - BString url; - if (message->FindString("url", &url) != B_OK) - url = m_url->Text(); - CurrentWebView()->LoadURL(url.String()); - break; - } - case GO_BACK: - CurrentWebView()->GoBack(); - break; - case GO_FORWARD: - CurrentWebView()->GoForward(); - break; - case STOP: - CurrentWebView()->StopLoading(); - break; + switch (message->what) { + case OPEN_LOCATION: + if (fURLTextControl) { + if (fURLTextControl->TextView()->IsFocus()) + fURLTextControl->TextView()->SelectAll(); + else + fURLTextControl->MakeFocus(true); + } + break; + case RELOAD: + CurrentWebView()->Reload(); + break; + case GOTO_URL: { + BString url; + if (message->FindString("url", &url) != B_OK) + url = fURLTextControl->Text(); + CurrentWebView()->LoadURL(url.String()); + break; + } + case GO_BACK: + CurrentWebView()->GoBack(); + break; + case GO_FORWARD: + CurrentWebView()->GoForward(); + break; + case STOP: + CurrentWebView()->StopLoading(); + break; - case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) - break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " - "the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->clear(); - break; - } + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to " + "clear the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); + break; + } - case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. - type_code type; - int32 countFound; - if (message->GetInfo("refs", &type, &countFound) != B_OK - || type != B_REF_TYPE) { - break; - } - if (countFound > 1) { - message->what = B_REFS_RECEIVED; - be_app->PostMessage(message); - break; - } - entry_ref ref; - if (message->FindRef("refs", &ref) != B_OK) - break; - BEntry entry(&ref, true); - BPath path; - if (!entry.Exists() || entry.GetPath(&path) != B_OK) - break; - CurrentWebView()->LoadURL(path.Path()); - break; - } + case B_SIMPLE_DATA: { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + CurrentWebView()->LoadURL(path.Path()); + break; + } - case TEXT_SIZE_INCREASE: - CurrentWebView()->IncreaseTextSize(); - break; - case TEXT_SIZE_DECREASE: - CurrentWebView()->DecreaseTextSize(); - break; - case TEXT_SIZE_RESET: - CurrentWebView()->ResetTextSize(); - break; + case TEXT_SIZE_INCREASE: + CurrentWebView()->IncreaseTextSize(); + break; + case TEXT_SIZE_DECREASE: + CurrentWebView()->DecreaseTextSize(); + break; + case TEXT_SIZE_RESET: + CurrentWebView()->ResetTextSize(); + break; - case TEXT_FIND_NEXT: - CurrentWebView()->FindString(m_findTextControl->Text(), true, - m_findCaseSensitiveCheckBox->Value()); - break; - case TEXT_FIND_PREVIOUS: - CurrentWebView()->FindString(m_findTextControl->Text(), false, - m_findCaseSensitiveCheckBox->Value()); - break; - case TEXT_SHOW_FIND_GROUP: - if (!m_findGroup->IsVisible()) - m_findGroup->SetVisible(true); - m_findTextControl->MakeFocus(true); - break; - case TEXT_HIDE_FIND_GROUP: - if (m_findGroup->IsVisible()) - m_findGroup->SetVisible(false); - break; + case TEXT_FIND_NEXT: + CurrentWebView()->FindString(fFindTextControl->Text(), true, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + CurrentWebView()->FindString(fFindTextControl->Text(), false, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!fFindGroup->IsVisible()) + fFindGroup->SetVisible(true); + fFindTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (fFindGroup->IsVisible()) + fFindGroup->SetVisible(false); + break; - case SHOW_DOWNLOAD_WINDOW: - message->AddUInt32("workspaces", Workspaces()); - be_app->PostMessage(message); - break; + case SHOW_DOWNLOAD_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; - case CLOSE_TAB: - if (m_tabManager->CountTabs() > 1) { - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = m_tabManager->SelectedTabIndex(); - delete m_tabManager->RemoveTab(index); - updateTabGroupVisibility(); - } else - PostMessage(B_QUIT_REQUESTED); - break; + case CLOSE_TAB: + if (fTabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = fTabManager->SelectedTabIndex(); + delete fTabManager->RemoveTab(index); + _UpdateTabGroupVisibility(); + } else + PostMessage(B_QUIT_REQUESTED); + break; - case TAB_CHANGED: { - // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = -1; - BWebView* webView = dynamic_cast(m_tabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - break; - SetCurrentWebView(webView); - if (webView) - updateTitle(webView->MainFrameTitle()); - else - updateTitle(""); - if (webView) { - m_url->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } - break; - } + case TAB_CHANGED: { + // This message may be received also when the last tab closed, i.e. with index == -1. + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + break; + SetCurrentWebView(webView); + if (webView) + _UpdateTitle(webView->MainFrameTitle()); + else + _UpdateTitle(""); + if (webView) { + fURLTextControl->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } + break; + } - default: - BWebWindow::MessageReceived(message); - break; - } + default: + BWebWindow::MessageReceived(message); + break; + } } -bool LauncherWindow::QuitRequested() + +bool +BrowserWindow::QuitRequested() { - // TODO: Check for modified form data and ask user for confirmation, etc. + // TODO: Check for modified form data and ask user for confirmation, etc. - // Iterate over all tabs to delete all BWebViews. - // Do this here, so WebKit tear down happens earlier. - while (m_tabManager->CountTabs() > 0) - delete m_tabManager->RemoveTab(0L); - SetCurrentWebView(0); + // Iterate over all tabs to delete all BWebViews. + // Do this here, so WebKit tear down happens earlier. + while (fTabManager->CountTabs() > 0) + delete fTabManager->RemoveTab(0L); + SetCurrentWebView(0); - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); - be_app->PostMessage(&message); - return true; + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; } -void LauncherWindow::MenusBeginning() + +void +BrowserWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = m_goMenu->RemoveItem(0L))) - delete menuItem; + BMenuItem* menuItem; + while ((menuItem = fGoMenu->RemoveItem(0L))) + delete menuItem; - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (!history->Lock()) - return; + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; - int32 count = history->countItems(); - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... - BString truncatedUrl(historyItem.url()); - be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); - menuItem = new BMenuItem(truncatedUrl, message); - m_goMenu->AddItem(menuItem); - } + int32 count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... + BString truncatedUrl(historyItem.url()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); + fGoMenu->AddItem(menuItem); + } - if (m_goMenu->CountItems() > 3) { - m_goMenu->AddSeparatorItem(); - m_goMenu->AddItem(new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY))); - } + if (fGoMenu->CountItems() > 3) { + fGoMenu->AddSeparatorItem(); + fGoMenu->AddItem(new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY))); + } - history->Unlock(); + history->Unlock(); } -void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) + +void +BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { - // Executed in app thread (new BWebPage needs to be created in app thread). - if (!webView) - webView = new BWebView("web view"); - webView->WebPage()->SetDownloadListener(m_downloadListener); + // Executed in app thread (new BWebPage needs to be created in app thread). + if (!webView) + webView = new BWebView("web view"); + webView->WebPage()->SetDownloadListener(fDownloadListener); - m_tabManager->AddTab(webView, "New tab"); + fTabManager->AddTab(webView, "New tab"); - if (url.Length()) - webView->LoadURL(url.String()); + if (url.Length()) + webView->LoadURL(url.String()); - if (select) { - m_tabManager->SelectTab(m_tabManager->CountTabs() - 1); - SetCurrentWebView(webView); - NavigationCapabilitiesChanged(false, false, false, webView); - if (m_url) { - m_url->SetText(url.String()); - m_url->MakeFocus(true); - } - } + if (select) { + fTabManager->SelectTab(fTabManager->CountTabs() - 1); + SetCurrentWebView(webView); + NavigationCapabilitiesChanged(false, false, false, webView); + if (fURLTextControl) { + fURLTextControl->SetText(url.String()); + fURLTextControl->MakeFocus(true); + } + } - updateTabGroupVisibility(); + _UpdateTabGroupVisibility(); } + // #pragma mark - Notification API -void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) + +void +BrowserWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) + +void +BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) { - // Always open new windows in the application thread, since - // creating a BWebView will try to grab the application lock. - // But our own WebPage may already try to lock us from within - // the application thread -> dead-lock. Thus we can't wait for - // a reply here. - BMessage message(NEW_TAB); - message.AddPointer("window", this); - message.AddString("url", url); - message.AddBool("select", primaryAction); - be_app->PostMessage(&message); + // Always open new windows in the application thread, since + // creating a BWebView will try to grab the application lock. + // But our own WebPage may already try to lock us from within + // the application thread -> dead-lock. Thus we can't wait for + // a reply here. + BMessage message(NEW_TAB); + message.AddPointer("window", this); + message.AddString("url", url); + message.AddBool("select", primaryAction); + be_app->PostMessage(&message); } -void LauncherWindow::NewPageCreated(BWebView* view) + +void +BrowserWindow::NewPageCreated(BWebView* view) { - newTab(BString(), true, view); + CreateNewTab(BString(), true, view); } -void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) + +void +BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { - BString status("Requesting: "); - status << url; - StatusChanged(status, view); + BString status("Requesting: "); + status << url; + StatusChanged(status, view); } -void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) + +void +BrowserWindow::LoadCommitted(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; // This hook is invoked when the load is commited. - if (m_url) - m_url->SetText(url.String()); + if (fURLTextControl) + fURLTextControl->SetText(url.String()); - BString status("Loading: "); - status << url; - StatusChanged(status, view); + BString status("Loading: "); + status << url; + StatusChanged(status, view); } -void LauncherWindow::LoadProgress(float progress, BWebView* view) + +void +BrowserWindow::LoadProgress(float progress, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_loadingProgressBar) { - if (progress < 100 && m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Show(); - m_loadingProgressBar->SetTo(progress); - } + if (fLoadingProgressBar) { + if (progress < 100 && fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Show(); + fLoadingProgressBar->SetTo(progress); + } } -void LauncherWindow::LoadFailed(const BString& url, BWebView* view) + +void +BrowserWindow::LoadFailed(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - BString status(url); - status << " failed."; - StatusChanged(status, view); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " failed."; + StatusChanged(status, view); + if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); } -void LauncherWindow::LoadFinished(const BString& url, BWebView* view) + +void +BrowserWindow::LoadFinished(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - BString status(url); - status << " finished."; - StatusChanged(status, view); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " finished."; + StatusChanged(status, view); + if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); - NavigationCapabilitiesChanged(m_BackButton->IsEnabled(), - m_ForwardButton->IsEnabled(), false, view); + NavigationCapabilitiesChanged(fBackButton->IsEnabled(), + fForwardButton->IsEnabled(), false, view); } -void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) + +void +BrowserWindow::ResizeRequested(float width, float height, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! - ResizeTo(width, height); + ResizeTo(width, height); } -void LauncherWindow::SetToolBarsVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetToolBarsVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetStatusBarVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetStatusBarVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetMenuBarVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetMenuBarVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetResizable(bool flag, BWebView* view) + +void +BrowserWindow::SetResizable(bool flag, BWebView* view) { - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! - if (flag) - SetFlags(Flags() & ~B_NOT_RESIZABLE); - else - SetFlags(Flags() | B_NOT_RESIZABLE); + if (flag) + SetFlags(Flags() & ~B_NOT_RESIZABLE); + else + SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::TitleChanged(const BString& title, BWebView* view) + +void +BrowserWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < m_tabManager->CountTabs(); i++) { - if (m_tabManager->ViewForTab(i) == view) { - m_tabManager->SetTabLabel(i, title); - break; - } - } - if (view != CurrentWebView()) - return; + for (int32 i = 0; i < fTabManager->CountTabs(); i++) { + if (fTabManager->ViewForTab(i) == view) { + fTabManager->SetTabLabel(i, title); + break; + } + } + if (view != CurrentWebView()) + return; - updateTitle(title); + _UpdateTitle(title); } -void LauncherWindow::StatusChanged(const BString& statusText, BWebView* view) + +void +BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_statusText) - m_statusText->SetText(statusText.String()); + if (fStatusText) + fStatusText->SetText(statusText.String()); } -void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, BWebView* view) + +void +BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_BackButton) - m_BackButton->SetEnabled(canGoBackward); - if (m_ForwardButton) - m_ForwardButton->SetEnabled(canGoForward); - if (m_StopButton) - m_StopButton->SetEnabled(canStop); + if (fBackButton) + fBackButton->SetEnabled(canGoBackward); + if (fForwardButton) + fForwardButton->SetEnabled(canGoForward); + if (fStopButton) + fStopButton->SetEnabled(canStop); } -void LauncherWindow::UpdateGlobalHistory(const BString& url) + +void +BrowserWindow::UpdateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, + +bool +BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, BWebView* view) { // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { - m_tabManager->SelectTab(view); + fTabManager->SelectTab(view); UpdateIfNeeded(); } - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - // Panel auto-destructs. - return panel->getAuthentication(message, inOutUser, inOutPassword, - inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, - &inOutRememberCredentials); + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + // Panel auto-destructs. + return panel->getAuthentication(message, inOutUser, inOutPassword, + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } -void LauncherWindow::updateTitle(const BString& title) + +// #pragma mark - private + + +void +BrowserWindow::_UpdateTitle(const BString& title) { - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << kApplicationName; + SetTitle(windowTitle.String()); } -void LauncherWindow::updateTabGroupVisibility() + +void +BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - //m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); - m_tabManager->SetCloseButtonsAvailable(m_tabManager->CountTabs() > 1); - Unlock(); + //fTabGroup->SetVisible(fTabManager->CountTabs() > 1); + fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); + Unlock(); } } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 018ac29a16..c646a4ab59 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -26,9 +26,9 @@ * (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 -#ifndef LauncherWindow_h -#define LauncherWindow_h #include "WebWindow.h" #include @@ -46,75 +46,91 @@ class TabManager; class BWebView; enum ToolbarPolicy { - HaveToolbar, - DoNotHaveToolbar + HaveToolbar, + DoNotHaveToolbar }; enum { - NEW_WINDOW = 'nwnd', - NEW_TAB = 'ntab', - WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc', - SHOW_DOWNLOAD_WINDOW = 'sdwd' + NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc', + SHOW_DOWNLOAD_WINDOW = 'sdwd' }; -class LauncherWindow : public BWebWindow { + +class BrowserWindow : public BWebWindow { public: - LauncherWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy = HaveToolbar); - virtual ~LauncherWindow(); + BrowserWindow(BRect frame, + const BMessenger& downloadListener, + ToolbarPolicy = HaveToolbar); + virtual ~BrowserWindow(); - virtual void DispatchMessage(BMessage* message, BHandler* target); - virtual void MessageReceived(BMessage* message); - virtual bool QuitRequested(); - virtual void MenusBeginning(); + virtual void DispatchMessage(BMessage* message, + BHandler* target); + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + virtual void MenusBeginning(); - void newTab(const BString& url, bool select, BWebView* webView = 0); + void CreateNewTab(const BString& url, bool select, + BWebView* webView = 0); private: - // WebPage notification API implementations - virtual void NavigationRequested(const BString& url, BWebView* view); - virtual void NewWindowRequested(const BString& url, bool primaryAction); - virtual void NewPageCreated(BWebView* view); - 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 TitleChanged(const BString& title, 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); - - void updateTitle(const BString &title); - void updateTabGroupVisibility(); + // WebPage notification API implementations + virtual void NavigationRequested(const BString& url, + BWebView* view); + virtual void NewWindowRequested(const BString& url, + bool primaryAction); + virtual void NewPageCreated(BWebView* view); + 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 TitleChanged(const BString& title, + 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: - BMessenger m_downloadListener; - BMenuBar* m_menuBar; - BMenu* m_goMenu; - IconButton* m_BackButton; - IconButton* m_ForwardButton; - IconButton* m_StopButton; - BButton* m_goButton; - BTextControl* m_url; - BStringView* m_statusText; - BStatusBar* m_loadingProgressBar; - BLayoutItem* m_findGroup; - BLayoutItem* m_tabGroup; - BTextControl* m_findTextControl; - BCheckBox* m_findCaseSensitiveCheckBox; - TabManager* m_tabManager; + void _UpdateTitle(const BString &title); + void _UpdateTabGroupVisibility(); + +private: + BMessenger fDownloadListener; + BMenuBar* fMenuBar; + BMenu* fGoMenu; + IconButton* fBackButton; + IconButton* fForwardButton; + IconButton* fStopButton; + BButton* fGoButton; + BTextControl* fURLTextControl; + BStringView* fStatusText; + BStatusBar* fLoadingProgressBar; + BLayoutItem* fFindGroup; + BLayoutItem* fTabGroup; + BTextControl* fFindTextControl; + BCheckBox* fFindCaseSensitiveCheckBox; + TabManager* fTabManager; }; -#endif // LauncherWindow_h + +#endif // BROWSER_WINDOW_H diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index 7c5246df11..e5a7e8afe4 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "BrowsingHistory.h" +#include "BrowserApp.h" #include #include #include @@ -262,7 +263,8 @@ bool BrowsingHistory::openSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher_BrowsingHistory") != B_OK) { + || path.Append(kApplicationName) != B_OK + || path.Append("BrowsingHistory") != B_OK) { return false; } return file.SetTo(path.Path(), mode) == B_OK; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 248e3bde44..fbbe932118 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "DownloadWindow.h" +#include "BrowserApp.h" #include "WebDownload.h" #include "WebPage.h" #include @@ -550,7 +551,8 @@ bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher_Downloads") != B_OK) { + || path.Append(kApplicationName) != B_OK + || path.Append("Downloads") != B_OK) { return false; } return file.SetTo(path.Path(), mode) == B_OK; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index fee9516509..f741a6a3e9 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -1,4 +1,4 @@ -resource app_signature "application/x-vnd.RJL-HaikuLauncher"; +resource app_signature "application/x-vnd.Haiku-WebPositive"; resource app_version { major = 0, @@ -6,8 +6,8 @@ resource app_version { minor = 1, variety = B_APPV_ALPHA, internal = 0, - short_info = "HaikuLauncher", - long_info = "HaikuLauncher ©2007-2010 The WebKit Haiku Project" + short_info = "WebPositive", + long_info = "WebPositive ©2007-2010 The WebKit Haiku Project" }; resource app_flags B_SINGLE_LAUNCH; From df6c7e475d73d6194330480ae044fdd054590ae5 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 18:26:46 +0000 Subject: [PATCH 075/293] The BWebDownload was using BWebPage for stuff, but the BWebPage can be long gone when a BWebDownload wanted to use it. Now the class is more self-sufficient. One example of the problem was clicking a link that opens a blank page, then closing that page while the download was still loading. 1) The download finished notification never arrived and 2) clicking to cancel the download would crash after the download finished, since really it had already selfdestructed... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@240 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index fbbe932118..44e5fa936e 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -272,6 +272,12 @@ public: // TOAST! return; } + 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; default: BGridView::MessageReceived(message); } From 0d3093e5d8e31fe0d7ea1e86de09633b0bcb6589 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 13:32:39 +0000 Subject: [PATCH 076/293] Implemented a neat new window management feature: When the app is asked to open a new file or url, check if there is already a window open on the current workspace, and if so, open a new tab in that window and bring it to front. ArgReceived() now reuses RefsReceived(), which has been extended to handle "url" string fields in the message, since ArgReceived() may also be asked to open urls and not only local files. The LOAD_AT_STARTING mechanism, which turned out to be broken for multiple args anyway, could be replaced, since RefsReceived() already buffers the message when it has been called earlier then ReadyToRun(). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@244 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 74 ++++++++++++++--------------- src/apps/webpositive/BrowserApp.h | 1 + 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 3dd0d7a25a..c23e7cbd6b 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -49,11 +49,6 @@ const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; const char* kApplicationName = "WebPositive"; -enum { - LOAD_AT_STARTING = 'lost' -}; - - BrowserApp::BrowserApp() : BApplication(kApplicationSignature) , fWindowCount(0) @@ -85,17 +80,18 @@ BrowserApp::AboutRequested() void BrowserApp::ArgvReceived(int32 argc, char** argv) { + BMessage message(B_REFS_RECEIVED); for (int i = 1; i < argc; i++) { const char* url = argv[i]; BEntry entry(argv[i], true); BPath path; if (entry.Exists() && entry.GetPath(&path) == B_OK) url = path.Path(); - BMessage message(LOAD_AT_STARTING); message.AddString("url", url); - message.AddBool("new window", fInitialized || i > 1); - PostMessage(&message); } + // Upon program launch, it will buffer a copy of the message, since + // ArgReceived() is called before ReadyToRun(). + RefsReceived(&message); } @@ -141,37 +137,8 @@ void BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { - case LOAD_AT_STARTING: { - BString url; - if (message->FindString("url", &url) != B_OK) - break; - bool openNewWindow = false; - message->FindBool("new window", &openNewWindow); - BrowserWindow* webWindow = NULL; - for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!openNewWindow) { - // stop at the first window - break; - } - } - if (webWindow) { - // There should always be at least one window open. If not, maybe we are about - // to quit anyway... - if (openNewWindow) { - // open a new window with an offset to the last window - _CreateNewWindow(url); - } else { - // load the URL in the first window - webWindow->CurrentWebView()->LoadURL(url.String()); - } - } - break; - } case B_SILENT_RELAUNCH: - _CreateNewWindow(""); + _CreateNewPage(""); break; case NEW_WINDOW: { BString url; @@ -238,8 +205,12 @@ BrowserApp::RefsReceived(BMessage* message) continue; BString url; url << path.Path(); - _CreateNewWindow(url); + _CreateNewPage(url); } + + BString url; + for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) + _CreateNewPage(url); } @@ -293,6 +264,31 @@ BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) } +void +BrowserApp::_CreateNewPage(const BString& url) +{ + uint32 workspace = 1 << current_workspace(); + + bool loadedInWindowOnCurrentWorkspace = false; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + BrowserWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (webWindow->Lock()) { + if (webWindow->Workspaces() & workspace) { + webWindow->CreateNewTab(url, true); + webWindow->Activate(); + loadedInWindowOnCurrentWorkspace = true; + } + webWindow->Unlock(); + } + if (loadedInWindowOnCurrentWorkspace) + return; + } + _CreateNewWindow(url); +} + + void BrowserApp::_CreateNewWindow(const BString& url) { diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index f834d41f62..17ae54735a 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -51,6 +51,7 @@ public: private: bool _OpenSettingsFile(BFile& file, uint32 mode); + void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, const BString& url, bool select); From e335cb654c2d4a70a8532c01f2a62bc8ad7e087a Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 13:50:06 +0000 Subject: [PATCH 077/293] Missing break in switch, but harmless in this case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@245 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index c23e7cbd6b..b12c380eff 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -177,6 +177,7 @@ BrowserApp::MessageReceived(BMessage* message) fDownloadWindow->Show(); else fDownloadWindow->Activate(); + break; } default: From e6809b325a8abd0f8a2b83e366b5483358fc15b6 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 20:48:31 +0000 Subject: [PATCH 078/293] Experimental integration of the main menu into the tab bar. Please tell me what you think, I am not 100% it's nicer than before. Can be easily reverted in any case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@248 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 16 ++++----- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/WebTabView.cpp | 49 +++++++++++++++++++++++--- src/apps/webpositive/WebTabView.h | 4 +++ 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ee11bf91ac..4a4413784d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -106,7 +106,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, if (toolbarPolicy == HaveToolbar) { // Menu - fMenuBar = new BMenuBar("Main menu"); +// BMenu* mainMenu = new BMenuBar("Main menu"); + BMenu* mainMenu = fTabManager->Menu(); BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); @@ -126,7 +127,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); - fMenuBar->AddItem(menu); + mainMenu->AddItem(menu); menu = new BMenu("Text"); menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); @@ -134,10 +135,10 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - fMenuBar->AddItem(menu); + mainMenu->AddItem(menu); fGoMenu = new BMenu("Go"); - fMenuBar->AddItem(fGoMenu); + mainMenu->AddItem(fGoMenu); // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); @@ -175,8 +176,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fLoadingProgressBar->Hide(); fLoadingProgressBar->SetBarHeight(12); - const float kInsetSpacing = 5; - const float kElementSpacing = 7; + const float kInsetSpacing = 3; + const float kElementSpacing = 5; fFindTextControl = new BTextControl("find", "Find:", "", new BMessage(TEXT_FIND_NEXT)); @@ -196,7 +197,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(fMenuBar) +// .Add(mainMenu) .Add(fTabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) @@ -228,7 +229,6 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStopButton = 0; fGoButton = 0; fURLTextControl = 0; - fMenuBar = 0; fStatusText = 0; fLoadingProgressBar = 0; diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c646a4ab59..e245f4d576 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -115,7 +115,6 @@ private: private: BMessenger fDownloadListener; - BMenuBar* fMenuBar; BMenu* fGoMenu; IconButton* fBackButton; IconButton* fForwardButton; diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 1b491385c0..b96e4a4fe9 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -863,10 +864,10 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); float tint = B_DARKEN_1_TINT; - if (!IsFront()) + if (!IsFront()) { + base = tint_color(base, tint); tint *= 1.02; - - base = tint_color(base, tint); + } if (fOverCloseRect) tint *= 1.2; @@ -916,6 +917,30 @@ TabManagerController::CloseTab(int32 index) } +// #pragma mark - TabButtonContainer + + +class TabButtonContainer : public BGroupView { +public: + TabButtonContainer() + : BGroupView(B_HORIZONTAL) + { + 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); + } +}; + + // #pragma mark - TabButton @@ -1058,7 +1083,6 @@ public: // #pragma mark - TabManager - TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : fController(new TabManagerController(this)), @@ -1068,9 +1092,17 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); + fMenu = new BMenu("Menu"); fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); - fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); + fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); + + BMenuBar* menuBar = new BMenuBar("Menu bar"); + menuBar->AddItem(fMenu); + TabButtonContainer* menuBarContainer = new TabButtonContainer(); + menuBarContainer->GroupLayout()->AddView(menuBar); + fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f); + fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); // fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); // fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); @@ -1101,6 +1133,13 @@ TabManager::Target() const } +BMenu* +TabManager::Menu() const +{ + return fMenu; +} + + BView* TabManager::TabGroup() const { diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 3f9f086755..e6d6c3abcd 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -38,6 +38,7 @@ enum { class BCardLayout; class BGroupView; +class BMenu; class TabContainerView; class TabManagerController; @@ -50,6 +51,8 @@ public: void SetTarget(const BMessenger& target); const BMessenger& Target() const; + BMenu* Menu() const; + BView* TabGroup() const; BView* ContainerView() const; @@ -69,6 +72,7 @@ public: void SetCloseButtonsAvailable(bool available); private: + BMenu* fMenu; BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; From e64e6d933a418060ceedf20dad4f19d4901dd5be Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 1 Mar 2010 04:25:55 +0000 Subject: [PATCH 079/293] Add shortcuts for using Alt-[1-9] to select that tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@249 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4a4413784d..7b1406161c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -79,6 +79,8 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', + + SELECT_TAB = 'sltb', }; @@ -249,6 +251,15 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + + // Add shortcuts to select a particular tab + for (int32 i = 1; i <= 9; i++) { + BMessage *selectTab = new BMessage(SELECT_TAB); + selectTab->AddInt32("tab index", i - 1); + char numStr[2]; + snprintf(numStr, sizeof(numStr), "%d", (int) i); + AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); + } be_app->PostMessage(WINDOW_OPENED); } @@ -396,6 +407,17 @@ BrowserWindow::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; + case SELECT_TAB: { + int32 index; + if (message->FindInt32("tab index", &index) == B_OK + && fTabManager->SelectedTabIndex() != index + && fTabManager->CountTabs() > index) { + fTabManager->SelectTab(index); + } + + break; + } + case TAB_CHANGED: { // This message may be received also when the last tab closed, i.e. with index == -1. int32 index; From 08d60e5886af0eddc762bababa1489d82c0bbe8a Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 1 Mar 2010 04:31:07 +0000 Subject: [PATCH 080/293] Shortcut Alt-0 selects the 10th tab (index 9.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@250 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 7b1406161c..6fc92f8b65 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -253,9 +253,12 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); // Add shortcuts to select a particular tab - for (int32 i = 1; i <= 9; i++) { + for (int32 i = 0; i <= 9; i++) { BMessage *selectTab = new BMessage(SELECT_TAB); - selectTab->AddInt32("tab index", i - 1); + if (i == 0) + selectTab->AddInt32("tab index", 9); + else + selectTab->AddInt32("tab index", i - 1); char numStr[2]; snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); From ddb431ba2136284cd2362719858fb51345d25f03 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 10:05:35 +0000 Subject: [PATCH 081/293] Made the integrated menu bar a build time configuration feature. I don't like it so much, since it somehow looks alien for no /really/ good reason. Maybe I'll integrate this option into the settings, when I get to those. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@253 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 +++++++-- src/apps/webpositive/BrowserWindow.h | 2 ++ src/apps/webpositive/WebTabView.cpp | 6 +++++- src/apps/webpositive/WebTabView.h | 4 ++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 6fc92f8b65..0fa866009e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -108,8 +108,11 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, if (toolbarPolicy == HaveToolbar) { // Menu -// BMenu* mainMenu = new BMenuBar("Main menu"); +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* mainMenu = fTabManager->Menu(); +#else + BMenu* mainMenu = new BMenuBar("Main menu"); +#endif BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); @@ -199,7 +202,9 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) -// .Add(mainMenu) +#if !INTEGRATE_MENU_INTO_TAB_BAR + .Add(mainMenu) +#endif .Add(fTabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e245f4d576..568a49670a 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -58,6 +58,8 @@ enum { SHOW_DOWNLOAD_WINDOW = 'sdwd' }; +#define INTEGRATE_MENU_INTO_TAB_BAR 0 + class BrowserWindow : public BWebWindow { public: diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index b96e4a4fe9..a4e073dc40 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1092,16 +1092,18 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); - fMenu = new BMenu("Menu"); fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); +#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->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); @@ -1133,11 +1135,13 @@ TabManager::Target() const } +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* TabManager::Menu() const { return fMenu; } +#endif BView* diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index e6d6c3abcd..69d7a032d9 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -51,7 +51,9 @@ public: void SetTarget(const BMessenger& target); const BMessenger& Target() const; +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* Menu() const; +#endif BView* TabGroup() const; BView* ContainerView() const; @@ -72,7 +74,9 @@ public: void SetCloseButtonsAvailable(bool available); private: +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; +#endif BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; From 10d5754b9273aa826a36beb7c614d0fe0ac0b1d6 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 17:41:43 +0000 Subject: [PATCH 082/293] Added BWebSettings and BPrivate::WebSettingsPrivate. Added all the wiring necessary. The only usable effect as of yet is that favicons arrive at the BrowserWindow. Favicons are stored in a database and are not fetched when they alreary exist. The application is expected to try and fetch an icon for a given url. This is currently done in BWebWindow when the URL for loading has been initiated. Otherwise it fetches the URL upon the new ICON_RECEIVED notification from the FrameLoaderClientHaiku. In any case it ends up at BWebWindow::IconReceived(), so derived classes don't have to worry about the difference. In any case, via BWebSettings, icons can also be fetched manually, like for the forthcomming autocompletion text control. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@257 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 4 +++- src/apps/webpositive/BrowserWindow.cpp | 7 +++++++ src/apps/webpositive/BrowserWindow.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b12c380eff..67ce27db15 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,8 +32,8 @@ #include "BrowserWindow.h" #include "DownloadWindow.h" #include "WebPage.h" +#include "WebSettings.h" #include "WebView.h" -#include "WebViewConstants.h" #include #include #include @@ -104,6 +104,8 @@ BrowserApp::ReadyToRun() BWebPage::InitializeOnce(); BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); + BWebSettings::SetPersistentStoragePath("/boot/home/config/settings/WebPositive"); + BFile settingsFile; BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0fa866009e..c72925f889 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -700,6 +700,13 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) } +void +BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) +{ + printf("BrowserWindow::IconReceived(%p, %p)\n", icon, view); +} + + void BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 568a49670a..9ef4426942 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -94,6 +94,8 @@ private: 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); From 606397473431bf7d5effa5bbfce7c224f652346b Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 18:46:15 +0000 Subject: [PATCH 083/293] Finished all the wiring necessary for favicon support. Send the NAVIGATION_REQUESTED notification again from the FrameLoaderClient, this way we can try to fetch the icon even earlier. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@259 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 +- src/apps/webpositive/WebTabView.cpp | 91 +++++++++++++++++++++++--- src/apps/webpositive/WebTabView.h | 9 ++- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c72925f889..0e811e4c8d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -321,6 +321,7 @@ BrowserWindow::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) url = fURLTextControl->Text(); + fTabManager->SetTabIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; } @@ -703,7 +704,7 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { - printf("BrowserWindow::IconReceived(%p, %p)\n", icon, view); + fTabManager->SetTabIcon(view, icon); } diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index a4e073dc40..bdbeb85c0b 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -31,6 +31,7 @@ #include "WebView.h" #include #include +#include #include #include #include @@ -146,6 +147,7 @@ public: 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; @@ -382,6 +384,17 @@ TabContainerView::RemoveTab(int32 index) } +TabView* +TabContainerView::TabAt(int32 index) const +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(index)); + if (item) + return item->Parent(); + return NULL; +} + + int32 TabContainerView::IndexOf(TabView* tab) const { @@ -738,6 +751,7 @@ private: class WebTabView : public TabView { public: WebTabView(TabManagerController* controller); + ~WebTabView(); virtual BSize MaxSize(); @@ -749,12 +763,15 @@ public: 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; @@ -764,6 +781,7 @@ private: WebTabView::WebTabView(TabManagerController* controller) : TabView(), + fIcon(NULL), fController(controller), fOverCloseRect(false), fClicked(false) @@ -771,11 +789,21 @@ WebTabView::WebTabView(TabManagerController* controller) } +WebTabView::~WebTabView() +{ + delete fIcon; +} + + BSize WebTabView::MaxSize() { - // Account for close button. + // Account for icon. BSize size(TabView::MaxSize()); + size.height = max_c(size.height, 16 + 8); + if (fIcon) + size.width += 16 + 8; + // Account for close button. size.width += size.height; return size; } @@ -788,6 +816,19 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, if (fController->CloseButtonsAvailable()) _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); + if (fIcon) { + BRect iconBounds(0, 0, 15, 15); + // clip to icon bounds, if they are smaller + if (iconBounds.Contains(fIcon->Bounds())) + iconBounds = fIcon->Bounds(); + BPoint iconPos(frame.left + 4, + frame.top + (frame.Height() - iconBounds.Height()) / 2); + iconBounds.OffsetTo(iconPos); + owner->SetDrawingMode(B_OP_OVER); + owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); + frame.left = frame.left + 16 + 8; + } + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); } @@ -843,6 +884,18 @@ WebTabView::MouseMoved(BPoint where, uint32 transit, } +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 { @@ -1181,16 +1234,11 @@ TabManager::SelectTab(int32 tabIndex) void -TabManager::SelectTab(BView* containedView) +TabManager::SelectTab(const BView* containedView) { - int32 count = fCardLayout->CountItems(); - for (int32 i = 0; i < count; i++) { - BLayoutItem* item = fCardLayout->ItemAt(i); - if (item->View() == containedView) { - SelectTab(i); - break; - } - } + int32 tabIndex = _TabIndexForContainedView(containedView); + if (tabIndex > 0) + SelectTab(tabIndex); } @@ -1252,6 +1300,16 @@ TabManager::SetTabLabel(int32 tabIndex, const char* label) } +void +TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) +{ + WebTabView* tab = dynamic_cast(fTabContainerView->TabAt( + _TabIndexForContainedView(containedView))); + if (tab) + tab->SetIcon(icon); +} + + void TabManager::SetCloseButtonsAvailable(bool available) { @@ -1261,3 +1319,16 @@ TabManager::SetCloseButtonsAvailable(bool available) fTabContainerView->Invalidate(); } + +int32 +TabManager::_TabIndexForContainedView(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; +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 69d7a032d9..93129b1b0c 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -36,6 +36,7 @@ enum { CLOSE_TAB = 'cltb' }; +class BBitmap; class BCardLayout; class BGroupView; class BMenu; @@ -61,7 +62,7 @@ public: BView* ViewForTab(int32 tabIndex) const; void SelectTab(int32 tabIndex); - void SelectTab(BView* containedView); + void SelectTab(const BView* containedView); int32 SelectedTabIndex() const; void CloseTab(int32 tabIndex); @@ -71,8 +72,14 @@ public: int32 CountTabs() const; void SetTabLabel(int32 tabIndex, const char* label); + void SetTabIcon(const BView* containedView, + const BBitmap* icon); void SetCloseButtonsAvailable(bool available); +private: + int32 _TabIndexForContainedView( + const BView* containedView) const; + private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; From 85fc02b33dc369109fe836474d3f0017f5b0bf1a Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 19:15:07 +0000 Subject: [PATCH 084/293] Use 18x18 as standard icon size, as it seems more common. Position the icon slightly more pleasing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@261 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index bdbeb85c0b..cda62fd150 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -795,14 +795,18 @@ WebTabView::~WebTabView() } +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, 16 + 8); + size.height = max_c(size.height, kIconSize + kIconInset * 2); if (fIcon) - size.width += 16 + 8; + size.width += kIconSize + kIconInset * 2; // Account for close button. size.width += size.height; return size; @@ -817,16 +821,16 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); if (fIcon) { - BRect iconBounds(0, 0, 15, 15); + BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1); // clip to icon bounds, if they are smaller if (iconBounds.Contains(fIcon->Bounds())) iconBounds = fIcon->Bounds(); - BPoint iconPos(frame.left + 4, - frame.top + (frame.Height() - iconBounds.Height()) / 2); + BPoint iconPos(frame.left + kIconInset - 1, + frame.top + floorf((frame.Height() - iconBounds.Height()) / 2)); iconBounds.OffsetTo(iconPos); owner->SetDrawingMode(B_OP_OVER); owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); - frame.left = frame.left + 16 + 8; + frame.left = frame.left + kIconSize + kIconInset * 2; } TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); From ea77068a8e791816cd78201bbe69af1e3083324d Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 00:49:48 +0000 Subject: [PATCH 085/293] Added shortcuts Cmd-Left/Right for going back/forward. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@263 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 37 +++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0e811e4c8d..3dc03d54de 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -281,21 +281,28 @@ BrowserWindow::~BrowserWindow() void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { - if (fURLTextControl && message->what == B_KEY_DOWN - && target == fURLTextControl->TextView()) { - // Handle B_RETURN in the URL text control. This is the easiest - // way to react *only* when the user presses the return key in the - // address bar, as opposed to trying to load whatever is in there when - // the text control just goes out of focus. - const char* bytes; - if (message->FindString("bytes", &bytes) == B_OK - && bytes[0] == B_RETURN) { - // Do it in such a way that the user sees the Go-button go down. - fGoButton->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - fGoButton->Invoke(); - snooze(1000); - fGoButton->SetValue(B_CONTROL_OFF); + const char* bytes; + int32 modifiers; + if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) + && message->FindString("bytes", &bytes) == B_OK + && message->FindInt32("modifiers", &modifiers) == B_OK) { + if (fURLTextControl && target == fURLTextControl->TextView()) { + // Handle B_RETURN in the URL text control. This is the easiest + // way to react *only* when the user presses the return key in the + // address bar, as opposed to trying to load whatever is in there when + // the text control just goes out of focus. + if (bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + fGoButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + fGoButton->Invoke(); + snooze(1000); + fGoButton->SetValue(B_CONTROL_OFF); + } + } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { + PostMessage(GO_BACK); + } else if (bytes[0] == B_RIGHT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { + PostMessage(GO_FORWARD); } } BWebWindow::DispatchMessage(message, target); From 39274de5a348d095a9960ca51fe0aafae2a16190 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 01:27:14 +0000 Subject: [PATCH 086/293] Double clicking beside the tabs opens a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@264 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index cda62fd150..4dbb0bfc70 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -127,6 +127,7 @@ public: virtual void TabSelected(int32 tabIndex) = 0; virtual bool HasFrames() = 0; virtual TabView* CreateTabView() = 0; + virtual void DoubleClickOutsideTabs() = 0; }; public: @@ -252,10 +253,15 @@ 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 (clicks > 1) + fController->DoubleClickOutsideTabs(); } @@ -715,6 +721,8 @@ class TabManagerController : public TabContainerView::Controller { public: TabManagerController(TabManager* manager); + virtual ~TabManagerController(); + virtual void TabSelected(int32 index) { fManager->SelectTab(index); @@ -727,6 +735,8 @@ public: virtual TabView* CreateTabView(); + virtual void DoubleClickOutsideTabs(); + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -739,9 +749,14 @@ public: return fCloseButtonsAvailable; } + void SetDoubleClickOutsideTabsMessage(const BMessage& message, + const BMessenger& target); + private: TabManager* fManager; bool fCloseButtonsAvailable; + BMessage* fDoubleClickOutsideTabsMessage; + BMessenger fTarget; }; @@ -955,11 +970,18 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, TabManagerController::TabManagerController(TabManager* manager) : fManager(manager), - fCloseButtonsAvailable(false) + fCloseButtonsAvailable(false), + fDoubleClickOutsideTabsMessage(NULL) { } +TabManagerController::~TabManagerController() +{ + delete fDoubleClickOutsideTabsMessage; +} + + TabView* TabManagerController::CreateTabView() { @@ -967,6 +989,13 @@ TabManagerController::CreateTabView() } +void +TabManagerController::DoubleClickOutsideTabs() +{ + fTarget.SendMessage(fDoubleClickOutsideTabsMessage); +} + + void TabManagerController::CloseTab(int32 index) { @@ -974,6 +1003,16 @@ TabManagerController::CloseTab(int32 index) } +void +TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, + const BMessenger& target) +{ + delete fDoubleClickOutsideTabsMessage; + fDoubleClickOutsideTabsMessage = new BMessage(message); + fTarget = target; +} + + // #pragma mark - TabButtonContainer @@ -1145,6 +1184,9 @@ 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); From fd5768c40d1eb05b345577285ec72788d7b115a5 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 12:38:07 +0000 Subject: [PATCH 087/293] Imported Beam auto completion framework, converted license to MIT (with permission from Oliver) and applied Haiku coding style. The base classes have been named such that they could become official Haiku API in the future. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@266 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleter.cpp | 212 ++++++++++ .../autocompletion/AutoCompleter.h | 154 +++++++ .../AutoCompleterDefaultImpl.cpp | 377 ++++++++++++++++++ .../autocompletion/AutoCompleterDefaultImpl.h | 92 +++++ .../autocompletion/TextControlCompleter.cpp | 118 ++++++ .../autocompletion/TextControlCompleter.h | 41 ++ 6 files changed, 994 insertions(+) create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.h create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.h diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp new file mode 100644 index 0000000000..c6583398f5 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -0,0 +1,212 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleter.h" + +#include +#include + +#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; +} + + +void +BAutoCompleter::ApplyChoice(bool hideChoices) +{ + if (fCompletionStyle) + fCompletionStyle->ApplyChoice(hideChoices); +} + + +void +BAutoCompleter::CancelChoice() +{ + if (fCompletionStyle) + fCompletionStyle->CancelChoice(); +} + + +void +BAutoCompleter::EditViewStateChanged() +{ + if (fCompletionStyle) + fCompletionStyle->EditViewStateChanged(); +} + + +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; +} diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h new file mode 100644 index 0000000000..443981f809 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -0,0 +1,154 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETEER_H +#define AUTO_COMPLETEER_H + +#include + +#include +#include + +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; + }; + + 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 void ApplyChoice(bool hideChoices = true) = 0; + virtual void CancelChoice() = 0; + + virtual void EditViewStateChanged() = 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 Select(int32 index); + bool SelectNext(bool wrap = false); + bool SelectPrevious(bool wrap = false); + + 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_COMPLETEER_H diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp new file mode 100644 index 0000000000..456a56f127 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -0,0 +1,377 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleterDefaultImpl.h" + +#include +#include +#include + + +// #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) +{ +} + + +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); +} + + +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); + + fFullEnteredText = completedText; + fPatternLength = choiceStr.Length(); + fEditView->SetEditViewState(completedText, + fPatternStartPos+choiceStr.Length()); + + if (hideChoices) + fChoiceView->HideChoices(); +} + + +void +BDefaultCompletionStyle::CancelChoice() +{ + if (!fChoiceView || !fEditView) + return; + if (fChoiceView->ChoicesAreShown()) { + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos+fPatternLength); + fChoiceView->HideChoices(); + Select(-1); + } +} + +void +BDefaultCompletionStyle::EditViewStateChanged() +{ + if (!fChoiceModel || !fChoiceView || !fEditView) + return; + + BString text; + int32 caretPos; + fEditView->GetEditViewState(text, &caretPos); + if (fFullEnteredText == text) + return; + fFullEnteredText = text; + 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 BM_INVOKED = 'bmin'; + + +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(BM_INVOKED)); + BListView::AttachedToWindow(); +} + + +void +BDefaultChoiceView::ListView::SelectionChanged() +{ + fCompleter->Select(CurrentSelection(0)); +} + + +void +BDefaultChoiceView::ListView::MessageReceived(BMessage* message) +{ + switch(message->what) { + case BM_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 textCol, backCol, matchCol; + if (IsSelected()) { + textCol = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + backCol = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); + } else { + textCol = ui_color(B_DOCUMENT_TEXT_COLOR); + backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + } + matchCol = tint_color(backCol, B_LIGHTEN_2_TINT); + + 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(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->SetHighColor(textCol); + owner->DrawString(fPreText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fMatchText.Length()) { + w = owner->StringWidth(fMatchText.String()); + owner->SetLowColor(matchCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fMatchText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fPostText.Length()) { + w = owner->StringWidth(fPostText.String()); + owner->SetLowColor(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fPostText.String(), BPoint(xPos, yPos)); + } +} + + +// #pragma mark - BDefaultChoiceView + + +BDefaultChoiceView::BDefaultChoiceView() + : + fWindow(NULL), + fListView(NULL) +{ + +} + + +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; iAddItem( + new ListItem(choiceModel->ChoiceAt(i)) + ); + } + + 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); + fWindow->AddChild(fListView); + + int32 visibleCount = min_c(count, 5); + 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); + + 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); +} + diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h new file mode 100644 index 0000000000..f697330915 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETER_DEFAULT_IMPL_H +#define AUTO_COMPLETER_DEFAULT_IMPL_H + +#include +#include + +#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 void ApplyChoice(bool hideChoices = true); + virtual void CancelChoice(); + + virtual void EditViewStateChanged(); + +private: + BString fFullEnteredText; + int32 fSelectedIndex; + int32 fPatternStartPos; + int32 fPatternLength; +}; + + +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(); + +private: + BWindow* fWindow; + ListView* fListView; +}; + +#endif // AUTO_COMPLETER_DEFAULT_IMPL_H diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp new file mode 100644 index 0000000000..e8e9cb0f52 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "TextControlCompleter.h" + +#include +#include + +#include "AutoCompleterDefaultImpl.h" + + +// #pragma mark - TextControlWrapper + + +TextControlCompleter::TextControlWrapper::TextControlWrapper( + BTextControl* textControl) + : + fTextControl(textControl) +{ +} + + +void +TextControlCompleter::TextControlWrapper::GetEditViewState(BString& text, + int32* caretPos) +{ + if (fTextControl && fTextControl->LockLooper()) { + text = fTextControl->Text(); + if (caretPos) { + int32 end; + fTextControl->TextView()->GetSelection(caretPos, &end); + } + fTextControl->UnlockLooper(); + } +} + + +void +TextControlCompleter::TextControlWrapper::SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength) +{ + if (fTextControl && fTextControl->LockLooper()) { + fTextControl->TextView()->SetText(text.String(), text.Length()); + fTextControl->TextView()->Select(caretPos, caretPos + selectionLength); + fTextControl->TextView()->ScrollToSelection(); + fTextControl->UnlockLooper(); + } +} + + +BRect +TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() +{ + BRect frame = fTextControl->TextView()->Bounds(); + frame = fTextControl->TextView()->ConvertToScreen(frame); + frame.InsetBy(-1, -3); + return frame; +} + + +TextControlCompleter::TextControlCompleter(BTextControl* textControl, + ChoiceModel* model, PatternSelector* patternSelector) + : + BAutoCompleter(new TextControlWrapper(textControl), model, + new BDefaultChoiceView(), patternSelector), + BMessageFilter(B_KEY_DOWN) +{ + textControl->TextView()->AddFilter(this); +} + + +TextControlCompleter::~TextControlCompleter() +{ +} + + +filter_result +TextControlCompleter::Filter(BMessage* message, BHandler** target) +{ + int32 rawChar, modifiers; + if (!target || message->FindInt32("raw_char", &rawChar) != B_OK + || message->FindInt32("modifiers", &modifiers) != B_OK) { + return B_DISPATCH_MESSAGE; + } + + switch (rawChar) { + case B_UP_ARROW: + SelectPrevious(); + return B_SKIP_MESSAGE; + case B_DOWN_ARROW: + SelectNext(); + return B_SKIP_MESSAGE; + case B_ESCAPE: + CancelChoice(); + return B_SKIP_MESSAGE; + case B_RETURN: + ApplyChoice(); + EditViewStateChanged(); + return B_SKIP_MESSAGE; + case B_TAB: { + // make sure that the choices-view is closed when tabbing out: + CancelChoice(); + return B_DISPATCH_MESSAGE; + } + default: + // 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; +} diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h new file mode 100644 index 0000000000..66ae3558c3 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ +#ifndef TEXT_CONTROL_COMPLETER_H +#define TEXT_CONTROL_COMPLETER_H + +#include + +#include "AutoCompleter.h" + + +class BTextControl; + +class TextControlCompleter : protected BAutoCompleter, public BMessageFilter { +public: + TextControlCompleter(BTextControl* textControl, + ChoiceModel* choiceModel = NULL, + PatternSelector* patternSelector = NULL); + virtual ~TextControlCompleter(); + +private: + virtual filter_result Filter(BMessage* message, BHandler** target); + + class TextControlWrapper : public EditView { + public: + TextControlWrapper(BTextControl* textControl); + virtual BRect GetAdjustmentFrame(); + virtual void GetEditViewState(BString& text, + int32* caretPos); + virtual void SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength = 0); + private: + BTextControl* fTextControl; + }; +}; + +#endif // TEXT_CONTROL_COMPLETER_H From 1a52acbc07a9c1b1024d76af44b5b8119fe98c39 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 18:40:50 +0000 Subject: [PATCH 088/293] Wired everything and improved the TextControlCompleter behavior a bit with regards to eating the B_RETURN key before we can dispatch in BrowserWindow. So autocompletion for URLs basically works. What's missing is: * Much better grouping of matches. * Fix the delay when the BrowsingHistory is first accessed (lazy loads itself from disk just then, ought to do it in the application thread after startup, which probably makes it unnoticable before the user starts typing a URL). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@268 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 68 +++++++++++++++++++ src/apps/webpositive/BrowserWindow.h | 2 + .../autocompletion/AutoCompleter.cpp | 11 +++ .../autocompletion/AutoCompleter.h | 2 + .../AutoCompleterDefaultImpl.cpp | 11 ++- .../autocompletion/AutoCompleterDefaultImpl.h | 1 + .../autocompletion/TextControlCompleter.cpp | 18 +++-- .../autocompletion/TextControlCompleter.h | 2 + 8 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3dc03d54de..8ffbfd8797 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" +#include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -93,6 +94,66 @@ layoutItemFor(BView* view) } +class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { + virtual void FetchChoicesFor(const BString& pattern) + { + int32 count = CountChoices(); + for (int32 i = 0; i < count; i++) { + delete reinterpret_cast( + fChoices.ItemAtFast(i)); + } + fChoices.MakeEmpty(); + + // Search through BrowsingHistory for any matches. + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + 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; + fChoices.AddItem(new BAutoCompleter::Choice(choiceText, + choiceText, matchPos, pattern.Length())); + } + + history->Unlock(); + } + + virtual int32 CountChoices() const + { + return fChoices.CountItems(); + } + + virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const + { + return reinterpret_cast( + fChoices.ItemAt(index)); + } + +private: + BList fChoices; +}; + + +class BrowsingHistoryPatternSelector : public BAutoCompleter::PatternSelector { + virtual void SelectPatternBounds(const BString& text, int32 caretPos, + int32* start, int32* length) + { + if (!start || !length) + return; + *start = 0; + *length = text.Length(); + } +}; + + +// #pragma mark - BrowserWindow + + BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, kApplicationName, @@ -228,6 +289,10 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fURLTextControl->MakeFocus(true); + fURLAutoCompleter = new TextControlCompleter(fURLTextControl, + new BrowsingHistoryChoiceModel(), + new BrowsingHistoryPatternSelector()); + fFindGroup = layoutItemFor(findGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); } else { @@ -236,6 +301,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStopButton = 0; fGoButton = 0; fURLTextControl = 0; + fURLAutoCompleter = 0; fStatusText = 0; fLoadingProgressBar = 0; @@ -275,6 +341,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, BrowserWindow::~BrowserWindow() { + delete fURLAutoCompleter; + delete fTabManager; } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9ef4426942..a296727c41 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -43,6 +43,7 @@ class BStringView; class BTextControl; class IconButton; class TabManager; +class TextControlCompleter; class BWebView; enum ToolbarPolicy { @@ -125,6 +126,7 @@ private: IconButton* fStopButton; BButton* fGoButton; BTextControl* fURLTextControl; + TextControlCompleter* fURLAutoCompleter; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; BLayoutItem* fFindGroup; diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index c6583398f5..98b659da40 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -148,6 +148,16 @@ BAutoCompleter::SelectPrevious(bool wrap) } +bool +BAutoCompleter::IsChoiceSelected() const +{ + if (fCompletionStyle) + return fCompletionStyle->IsChoiceSelected(); + else + return false; +} + + void BAutoCompleter::ApplyChoice(bool hideChoices) { @@ -210,3 +220,4 @@ BAutoCompleter::SetCompletionStyle(CompletionStyle* style) delete fCompletionStyle; fCompletionStyle = style; } + diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 443981f809..33cb8ceb77 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -97,6 +97,7 @@ public: 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 void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; @@ -135,6 +136,7 @@ protected: bool Select(int32 index); bool SelectNext(bool wrap = false); bool SelectPrevious(bool wrap = false); + bool IsChoiceSelected() const; void ApplyChoice(bool hideChoices = true); void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 456a56f127..6f41c235a0 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -96,6 +96,13 @@ BDefaultCompletionStyle::SelectPrevious(bool wrap) } +bool +BDefaultCompletionStyle::IsChoiceSelected() const +{ + return fSelectedIndex >= 0; +} + + void BDefaultCompletionStyle::ApplyChoice(bool hideChoices) { @@ -112,8 +119,10 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) fEditView->SetEditViewState(completedText, fPatternStartPos+choiceStr.Length()); - if (hideChoices) + if (hideChoices) { fChoiceView->HideChoices(); + Select(-1); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index f697330915..81bca0fd1e 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -35,6 +35,7 @@ public: virtual bool Select(int32 index); virtual bool SelectNext(bool wrap = false); virtual bool SelectPrevious(bool wrap = false); + virtual bool IsChoiceSelected() const; virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp index e8e9cb0f52..6b3c257602 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -10,6 +10,7 @@ #include #include +#include #include "AutoCompleterDefaultImpl.h" @@ -58,7 +59,7 @@ TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() { BRect frame = fTextControl->TextView()->Bounds(); frame = fTextControl->TextView()->ConvertToScreen(frame); - frame.InsetBy(-1, -3); + frame.InsetBy(0, -3); return frame; } @@ -68,14 +69,16 @@ TextControlCompleter::TextControlCompleter(BTextControl* textControl, : BAutoCompleter(new TextControlWrapper(textControl), model, new BDefaultChoiceView(), patternSelector), - BMessageFilter(B_KEY_DOWN) + BMessageFilter(B_KEY_DOWN), + fTextControl(textControl) { - textControl->TextView()->AddFilter(this); + fTextControl->TextView()->AddFilter(this); } TextControlCompleter::~TextControlCompleter() { + fTextControl->TextView()->RemoveFilter(this); } @@ -99,9 +102,12 @@ TextControlCompleter::Filter(BMessage* message, BHandler** target) CancelChoice(); return B_SKIP_MESSAGE; case B_RETURN: - ApplyChoice(); - EditViewStateChanged(); - return B_SKIP_MESSAGE; + 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(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h index 66ae3558c3..89c5125f2e 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.h +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -36,6 +36,8 @@ private: private: BTextControl* fTextControl; }; +private: + BTextControl* fTextControl; }; #endif // TEXT_CONTROL_COMPLETER_H From 0cf34b77b1bcdb6e2d4b0d527026f0f47e4588f3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 18:56:42 +0000 Subject: [PATCH 089/293] Ok, the most simplistic way to avoid having too many similars in the autocompletion choices is to find the "base url" (I am taking the string between :// and the next /) and avoid adding any more urls with the same base URL. Seems to work reasonably well. If anyone has any smarter ideas, please speak up! :-) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@269 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8ffbfd8797..12008f1362 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -109,6 +109,8 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { if (!history->Lock()) return; + BString lastBaseURL; + count = history->countItems(); for (int32 i = 0; i < count; i++) { BrowsingHistoryItem item = history->historyItemAt(i); @@ -116,6 +118,14 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { int32 matchPos = choiceText.IFindFirst(pattern); if (matchPos < 0) continue; + if (lastBaseURL.Length() > 0 + && choiceText.FindFirst(lastBaseURL) >= 0) { + continue; + } + int32 baseURLStart = choiceText.FindFirst("://") + 3; + int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); + lastBaseURL.SetTo(choiceText.String() + baseURLStart, + baseURLEnd - baseURLStart); fChoices.AddItem(new BAutoCompleter::Choice(choiceText, choiceText, matchPos, pattern.Length())); } From b943093b1bfd7178362d88c3bba8b4ce11989a3e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 21:23:44 +0000 Subject: [PATCH 090/293] Preload the browsing history after application start. This avoids the delay when beginning to type something in the URL text field and the autocompletion invoked the BrowsingHistory for the first time. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@270 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 67ce27db15..d4e05ac283 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -30,6 +30,7 @@ #include "BrowserApp.h" #include "BrowserWindow.h" +#include "BrowsingHistory.h" #include "DownloadWindow.h" #include "WebPage.h" #include "WebSettings.h" @@ -47,7 +48,7 @@ const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; const char* kApplicationName = "WebPositive"; - +static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh'; BrowserApp::BrowserApp() : BApplication(kApplicationSignature) @@ -132,6 +133,7 @@ BrowserApp::ReadyToRun() BMessenger(fDownloadWindow)); window->Show(); } + PostMessage(PRELOAD_BROWSING_HISTORY); } @@ -139,6 +141,9 @@ void BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { + case PRELOAD_BROWSING_HISTORY: + BrowsingHistory::defaultInstance(); + break; case B_SILENT_RELAUNCH: _CreateNewPage(""); break; From 572a465779ef393f440ace942e7617dcd227dc6a Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 21:24:06 +0000 Subject: [PATCH 091/293] Fixed header guards, thanks Ryan! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@271 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/AutoCompleter.h | 7 +++---- .../webpositive/autocompletion/AutoCompleterDefaultImpl.h | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 33cb8ceb77..8b5cb7be37 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -5,9 +5,8 @@ * Authors: * Oliver Tappe */ - -#ifndef AUTO_COMPLETEER_H -#define AUTO_COMPLETEER_H +#ifndef _AUTO_COMPLETER_H +#define _AUTO_COMPLETER_H #include @@ -153,4 +152,4 @@ private: }; -#endif // AUTO_COMPLETEER_H +#endif // _AUTO_COMPLETER_H diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index 81bca0fd1e..cf01dbbad1 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -5,9 +5,8 @@ * Authors: * Oliver Tappe */ - -#ifndef AUTO_COMPLETER_DEFAULT_IMPL_H -#define AUTO_COMPLETER_DEFAULT_IMPL_H +#ifndef _AUTO_COMPLETER_DEFAULT_IMPL_H +#define _AUTO_COMPLETER_DEFAULT_IMPL_H #include #include @@ -90,4 +89,4 @@ private: ListView* fListView; }; -#endif // AUTO_COMPLETER_DEFAULT_IMPL_H +#endif // _AUTO_COMPLETER_DEFAULT_IMPL_H From e25584f3c591de0311578ca53f735e5950d46cf3 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:07:06 +0000 Subject: [PATCH 092/293] Wrap main thread in try-catch-block, in order to get a stack trace next time we hit that recursive init exception. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@273 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index d4e05ac283..df6b01832e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -329,9 +330,13 @@ BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, int main(int, char**) { - new BrowserApp(); - be_app->Run(); - delete be_app; + try { + new BrowserApp(); + be_app->Run(); + delete be_app; + } catch (...) { + debugger("Exception caught."); + } return 0; } From dad87be6e5f69b9a3b7094c0bb9aada9dfe04caa Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:07:37 +0000 Subject: [PATCH 093/293] Better to darken the match color, this makes it visible also in non-selected choice items. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@274 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/AutoCompleterDefaultImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 6f41c235a0..7818f5b81b 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -251,7 +251,7 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, textCol = ui_color(B_DOCUMENT_TEXT_COLOR); backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); } - matchCol = tint_color(backCol, B_LIGHTEN_2_TINT); + matchCol = tint_color(backCol, (B_NO_TINT + B_DARKEN_1_TINT) / 2); BFont font; font_height fontHeight; From c1bbe7400c2108119a06c4c5b9cd1c4d616f9338 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:20:17 +0000 Subject: [PATCH 094/293] Improved coding style and the looks of the matched pattern in choices. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@275 94f232f2-1747-11df-bad5-a5bfde151594 --- .../AutoCompleterDefaultImpl.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 7818f5b81b..95ce32c7a0 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -243,15 +243,19 @@ void BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, bool complete) { - rgb_color textCol, backCol, matchCol; + rgb_color textColor; + rgb_color nonMatchTextColor; + rgb_color backColor; + rgb_color matchColor; if (IsSelected()) { - textCol = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); - backCol = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); + textColor = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + backColor = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); } else { - textCol = ui_color(B_DOCUMENT_TEXT_COLOR); - backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + textColor = ui_color(B_DOCUMENT_TEXT_COLOR); + backColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); } - matchCol = tint_color(backCol, (B_NO_TINT + B_DARKEN_1_TINT) / 2); + matchColor = tint_color(backColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2); + nonMatchTextColor = tint_color(backColor, 1.7); BFont font; font_height fontHeight; @@ -262,26 +266,28 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, float w; if (fPreText.Length()) { w = owner->StringWidth(fPreText.String()); - owner->SetLowColor(backCol); + owner->SetLowColor(backColor); owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), B_SOLID_LOW); - owner->SetHighColor(textCol); + owner->SetHighColor(nonMatchTextColor); owner->DrawString(fPreText.String(), BPoint(xPos, yPos)); xPos += w; } if (fMatchText.Length()) { w = owner->StringWidth(fMatchText.String()); - owner->SetLowColor(matchCol); + 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(backCol); + 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)); } } From c6662bd928d11cac7ff7c27bc74819c9506c66fd Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:22:50 +0000 Subject: [PATCH 095/293] PatternSelector has a default implementation... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@276 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 12008f1362..c29896f34f 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -149,18 +149,6 @@ private: }; -class BrowsingHistoryPatternSelector : public BAutoCompleter::PatternSelector { - virtual void SelectPatternBounds(const BString& text, int32 caretPos, - int32* start, int32* length) - { - if (!start || !length) - return; - *start = 0; - *length = text.Length(); - } -}; - - // #pragma mark - BrowserWindow @@ -300,8 +288,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fURLTextControl->MakeFocus(true); fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel(), - new BrowsingHistoryPatternSelector()); + new BrowsingHistoryChoiceModel()); fFindGroup = layoutItemFor(findGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); From d0417c565a1a418ece0406d288dcd2e971b5d447 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:57:46 +0000 Subject: [PATCH 096/293] Implemented basic settings window skeleton. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@277 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 63 +++++++---- src/apps/webpositive/BrowserApp.h | 4 + src/apps/webpositive/BrowserWindow.cpp | 2 + src/apps/webpositive/BrowserWindow.h | 3 +- src/apps/webpositive/SettingsWindow.cpp | 138 ++++++++++++++++++++++++ src/apps/webpositive/SettingsWindow.h | 55 ++++++++++ 6 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 src/apps/webpositive/SettingsWindow.cpp create mode 100644 src/apps/webpositive/SettingsWindow.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index df6b01832e..81fcce7b28 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,6 +32,7 @@ #include "BrowserWindow.h" #include "BrowsingHistory.h" #include "DownloadWindow.h" +#include "SettingsWindow.h" #include "WebPage.h" #include "WebSettings.h" #include "WebView.h" @@ -52,12 +53,14 @@ const char* kApplicationName = "WebPositive"; static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh'; BrowserApp::BrowserApp() - : BApplication(kApplicationSignature) - , fWindowCount(0) - , fLastWindowFrame(100, 100, 700, 750) - , fLaunchRefsMessage(0) - , fInitialized(false) - , fDownloadWindow(0) + : + BApplication(kApplicationSignature), + fWindowCount(0), + fLastWindowFrame(100, 100, 700, 750), + fLaunchRefsMessage(0), + fInitialized(false), + fDownloadWindow(NULL), + fSettingsWindow(NULL) { } @@ -111,17 +114,26 @@ BrowserApp::ReadyToRun() BFile settingsFile; BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); + BRect settingsWindowFrame; bool showDownloads = false; if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); - settingsArchive.FindRect("window frame", &windowFrameFromSettings); - settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); - settingsArchive.FindBool("show downloads", &showDownloads); + BRect rect; + if (settingsArchive.FindRect("window frame", &rect) == B_OK) + windowFrameFromSettings = rect; + if (settingsArchive.FindRect("downloads window frame", &rect) == B_OK) + downloadWindowFrame = rect; + if (settingsArchive.FindRect("settings window frame", &rect) == B_OK) + settingsWindowFrame = rect; + bool flag; + if (settingsArchive.FindBool("show downloads", &flag) == B_OK) + showDownloads = flag; } fLastWindowFrame = windowFrameFromSettings; fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fSettingsWindow = new SettingsWindow(settingsWindowFrame); fInitialized = true; @@ -176,17 +188,12 @@ BrowserApp::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; - case SHOW_DOWNLOAD_WINDOW: { - BAutolock _(fDownloadWindow); - uint32 workspaces; - if (message->FindUInt32("workspaces", &workspaces) == B_OK) - fDownloadWindow->SetWorkspaces(workspaces); - if (fDownloadWindow->IsHidden()) - fDownloadWindow->Show(); - else - fDownloadWindow->Activate(); + case SHOW_DOWNLOAD_WINDOW: + _ShowWindow(message, fDownloadWindow); + break; + case SHOW_SETTINGS_WINDOW: + _ShowWindow(message, fSettingsWindow); break; - } default: BApplication::MessageReceived(message); @@ -251,6 +258,10 @@ BrowserApp::QuitRequested() settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); fDownloadWindow->Unlock(); } + if (fSettingsWindow->Lock()) { + settingsArchive.AddRect("settings window frame", fSettingsWindow->Frame()); + fSettingsWindow->Unlock(); + } settingsArchive.Flatten(&settingsFile); } @@ -324,6 +335,20 @@ BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, } +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 - diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 17ae54735a..6b5402ba9a 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -35,6 +35,7 @@ class BFile; class DownloadWindow; class BrowserWindow; +class SettingsWindow; class BrowserApp : public BApplication { @@ -55,6 +56,8 @@ private: void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, const BString& url, bool select); + void _ShowWindow(const BMessage* message, + BWindow* window); private: int fWindowCount; @@ -63,6 +66,7 @@ private: bool fInitialized; DownloadWindow* fDownloadWindow; + SettingsWindow* fSettingsWindow; }; diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c29896f34f..fc01924a22 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -187,6 +187,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -473,6 +474,7 @@ BrowserWindow::MessageReceived(BMessage* message) break; case SHOW_DOWNLOAD_WINDOW: + case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); be_app->PostMessage(message); break; diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index a296727c41..0fafb1ec2e 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -56,7 +56,8 @@ enum { NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', - SHOW_DOWNLOAD_WINDOW = 'sdwd' + SHOW_DOWNLOAD_WINDOW = 'sdwd', + SHOW_SETTINGS_WINDOW = 'sswd' }; #define INTEGRATE_MENU_INTO_TAB_BAR 0 diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp new file mode 100644 index 0000000000..77364539fe --- /dev/null +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 "BrowserApp.h" +#include "WebSettings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +enum { + MSG_OK = 'aply', + MSG_CANCEL = 'cncl', + MSG_REVERT = 'rvrt', +}; + + +SettingsWindow::SettingsWindow(BRect frame) + : + BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) +{ + SetLayout(new BGroupLayout(B_VERTICAL)); + + fOkButton = new BButton("OK", new BMessage(MSG_OK)); + fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); + fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); + + float spacing = be_control_look->DefaultItemSpacing(); + + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(BGridLayoutBuilder(spacing, spacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) + .Add(fRevertButton) + .AddGlue() + .Add(fCancelButton) + .Add(fOkButton) + .SetInsets(spacing, spacing, spacing, spacing) + ) + ); + + fOkButton->MakeDefault(true); + + if (!frame.IsValid()) + CenterOnScreen(); + + // Start hidden + Hide(); + Show(); +} + + +SettingsWindow::~SettingsWindow() +{ +} + + +void +SettingsWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_OK: + _ApplySettings(); + PostMessage(B_QUIT_REQUESTED); + break; + case MSG_CANCEL: + _RevertSettings(); + PostMessage(B_QUIT_REQUESTED); + break; + case MSG_REVERT: + _RevertSettings(); + break; + default: + BWindow::MessageReceived(message); + break; + } +} + + +bool +SettingsWindow::QuitRequested() +{ + if (!IsHidden()) + Hide(); + return false; +} + + +// #pragma mark - private + + +void +SettingsWindow::_ApplySettings() +{ +} + + +void +SettingsWindow::_RevertSettings() +{ +} + + diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h new file mode 100644 index 0000000000..22ff3f7c10 --- /dev/null +++ b/src/apps/webpositive/SettingsWindow.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + +class BButton; + + +class SettingsWindow : public BWindow { +public: + SettingsWindow(BRect frame); + virtual ~SettingsWindow(); + + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + +private: + void _ApplySettings(); + void _RevertSettings(); + +private: + BButton* fOkButton; + BButton* fCancelButton; + BButton* fRevertButton; +}; + + +#endif // SETTINGS_WINDOW_H + From 75c44a83ca47dbc46c82c9d972c2b22eaf8f946a Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 11:08:50 +0000 Subject: [PATCH 097/293] Moved some utility stuff into new subfolder "support". Some of these needs to be removed too, once WebPositive is moved into Haiku. SettingsMessage comes straight from MediaPlayer. Should be moved into src/kits/shared eventually. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@278 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/{ => support}/DateTime.cpp | 0 src/apps/webpositive/{ => support}/DateTime.h | 0 .../webpositive/{ => support}/IconButton.cpp | 0 .../webpositive/{ => support}/IconButton.h | 0 .../webpositive/{ => support}/IconUtils.h | 0 .../webpositive/support/SettingsMessage.cpp | 336 ++++++++++++++++++ .../webpositive/support/SettingsMessage.h | 79 ++++ 7 files changed, 415 insertions(+) rename src/apps/webpositive/{ => support}/DateTime.cpp (100%) rename src/apps/webpositive/{ => support}/DateTime.h (100%) rename src/apps/webpositive/{ => support}/IconButton.cpp (100%) rename src/apps/webpositive/{ => support}/IconButton.h (100%) rename src/apps/webpositive/{ => support}/IconUtils.h (100%) create mode 100644 src/apps/webpositive/support/SettingsMessage.cpp create mode 100644 src/apps/webpositive/support/SettingsMessage.h diff --git a/src/apps/webpositive/DateTime.cpp b/src/apps/webpositive/support/DateTime.cpp similarity index 100% rename from src/apps/webpositive/DateTime.cpp rename to src/apps/webpositive/support/DateTime.cpp diff --git a/src/apps/webpositive/DateTime.h b/src/apps/webpositive/support/DateTime.h similarity index 100% rename from src/apps/webpositive/DateTime.h rename to src/apps/webpositive/support/DateTime.h diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/support/IconButton.cpp similarity index 100% rename from src/apps/webpositive/IconButton.cpp rename to src/apps/webpositive/support/IconButton.cpp diff --git a/src/apps/webpositive/IconButton.h b/src/apps/webpositive/support/IconButton.h similarity index 100% rename from src/apps/webpositive/IconButton.h rename to src/apps/webpositive/support/IconButton.h diff --git a/src/apps/webpositive/IconUtils.h b/src/apps/webpositive/support/IconUtils.h similarity index 100% rename from src/apps/webpositive/IconUtils.h rename to src/apps/webpositive/support/IconUtils.h diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp new file mode 100644 index 0000000000..dad98820b2 --- /dev/null +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -0,0 +1,336 @@ +/* + * Copyright 2008, Stephan Aßmus . + * 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 +#include +#include + + +SettingsMessage::SettingsMessage(directory_which directory, + const char* filename) + : BMessage('pref') +{ + fStatus = find_directory(directory, &fPath); + + if (fStatus == B_OK) + fStatus = fPath.Append(filename); + + if (fStatus == B_OK) + fStatus = Load(); +} + + +SettingsMessage::~SettingsMessage() +{ + Save(); +} + + +status_t +SettingsMessage::InitCheck() const +{ + return fStatus; +} + + +status_t +SettingsMessage::Load() +{ + 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 +{ + 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; +} + + +// #pragma mark - + + +status_t +SettingsMessage::SetValue(const char* name, bool value) +{ + if (ReplaceBool(name, value) == B_OK) + return B_OK; + return AddBool(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int8 value) +{ + if (ReplaceInt8(name, value) == B_OK) + return B_OK; + return AddInt8(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int16 value) +{ + if (ReplaceInt16(name, value) == B_OK) + return B_OK; + return AddInt16(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int32 value) +{ + if (ReplaceInt32(name, value) == B_OK) + return B_OK; + return AddInt32(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, uint32 value) +{ + if (ReplaceInt32(name, (int32)value) == B_OK) + return B_OK; + return AddInt32(name, (int32)value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int64 value) +{ + if (ReplaceInt64(name, value) == B_OK) + return B_OK; + return AddInt64(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, float value) +{ + if (ReplaceFloat(name, value) == B_OK) + return B_OK; + return AddFloat(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, double value) +{ + if (ReplaceDouble(name, value) == B_OK) + return B_OK; + return AddDouble(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const char* value) +{ + if (ReplaceString(name, value) == B_OK) + return B_OK; + return AddString(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BString& value) +{ + return SetValue(name, value.String()); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BPoint& value) +{ + if (ReplacePoint(name, value) == B_OK) + return B_OK; + return AddPoint(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BRect& value) +{ + if (ReplaceRect(name, value) == B_OK) + return B_OK; + return AddRect(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const entry_ref& value) +{ + if (ReplaceRef(name, &value) == B_OK) + return B_OK; + return AddRef(name, &value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BMessage* value) +{ + if (ReplaceMessage(name, value) == B_OK) + return B_OK; + return AddMessage(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BFlattenable* value) +{ + if (ReplaceFlat(name, const_cast(value)) == B_OK) + return B_OK; + return AddFlat(name, const_cast(value)); +} + + +// #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 +{ + int32 value; + if (FindInt32(name, &value) != B_OK) + return defaultValue; + return (uint32)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; +} + + +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; +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h new file mode 100644 index 0000000000..f98121b5bb --- /dev/null +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -0,0 +1,79 @@ +/* + * Copyright 2008 Stephan Aßmus . + * 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 +#include +#include + +class BString; + +class SettingsMessage : public BMessage { +public: + SettingsMessage(directory_which directory, + const char* filename); + virtual ~SettingsMessage(); + + + status_t InitCheck() const; + status_t Load(); + status_t Save() const; + + 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); + + 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; + 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; + +private: + BPath fPath; + status_t fStatus; +}; + +#endif // SETTINGS_MESSAGE_H From b5cd3e842fd3e758ea8fdb95ff00b38835ed8aec Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 11:23:06 +0000 Subject: [PATCH 098/293] Reworked BrowserApp to use SettingsMessage. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@279 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 81 +++++++++---------------- src/apps/webpositive/BrowserApp.h | 5 +- src/apps/webpositive/SettingsWindow.cpp | 7 ++- src/apps/webpositive/SettingsWindow.h | 6 +- 4 files changed, 43 insertions(+), 56 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 81fcce7b28..aaffc30a1e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,6 +32,7 @@ #include "BrowserWindow.h" #include "BrowsingHistory.h" #include "DownloadWindow.h" +#include "SettingsMessage.h" #include "SettingsWindow.h" #include "WebPage.h" #include "WebSettings.h" @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -59,6 +59,7 @@ BrowserApp::BrowserApp() fLastWindowFrame(100, 100, 700, 750), fLaunchRefsMessage(0), fInitialized(false), + fSettings(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) { @@ -68,6 +69,7 @@ BrowserApp::BrowserApp() BrowserApp::~BrowserApp() { delete fLaunchRefsMessage; + delete fSettings; } @@ -109,31 +111,28 @@ BrowserApp::ReadyToRun() BWebPage::InitializeOnce(); BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); - BWebSettings::SetPersistentStoragePath("/boot/home/config/settings/WebPositive"); + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK + && path.Append(kApplicationName) == B_OK + && create_directory(path.Path(), 0777) == B_OK) { - BFile settingsFile; - BRect windowFrameFromSettings = fLastWindowFrame; - BRect downloadWindowFrame(100, 100, 300, 250); - BRect settingsWindowFrame; - bool showDownloads = false; - if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { - BMessage settingsArchive; - settingsArchive.Unflatten(&settingsFile); - BRect rect; - if (settingsArchive.FindRect("window frame", &rect) == B_OK) - windowFrameFromSettings = rect; - if (settingsArchive.FindRect("downloads window frame", &rect) == B_OK) - downloadWindowFrame = rect; - if (settingsArchive.FindRect("settings window frame", &rect) == B_OK) - settingsWindowFrame = rect; - bool flag; - if (settingsArchive.FindBool("show downloads", &flag) == B_OK) - showDownloads = flag; + BWebSettings::SetPersistentStoragePath(path.Path()); } - fLastWindowFrame = windowFrameFromSettings; + + BString mainSettingsPath(kApplicationName); + mainSettingsPath << "/Application"; + fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, + mainSettingsPath.String()); + + fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); + BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", + BRect(100, 100, 300, 250)); + BRect settingsWindowFrame = fSettings->GetValue("settings window frame", + BRect()); + bool showDownloads = fSettings->GetValue("show downloads", false); fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); - fSettingsWindow = new SettingsWindow(settingsWindowFrame); + fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); fInitialized = true; @@ -249,41 +248,21 @@ BrowserApp::QuitRequested() } } - BFile settingsFile; - if (_OpenSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { - BMessage settingsArchive; - settingsArchive.AddRect("window frame", fLastWindowFrame); - if (fDownloadWindow->Lock()) { - settingsArchive.AddRect("downloads window frame", fDownloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); - fDownloadWindow->Unlock(); - } - if (fSettingsWindow->Lock()) { - settingsArchive.AddRect("settings window frame", fSettingsWindow->Frame()); - fSettingsWindow->Unlock(); - } - settingsArchive.Flatten(&settingsFile); + 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(); } return true; } -bool -BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) -{ - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append(kApplicationName) != B_OK - || create_directory(path.Path(), 0777) != B_OK - || path.Append("Application") != B_OK) { - return false; - } - - return file.SetTo(path.Path(), mode) == B_OK; -} - - void BrowserApp::_CreateNewPage(const BString& url) { diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 6b5402ba9a..531a88ffe0 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -32,9 +32,9 @@ #include #include -class BFile; class DownloadWindow; class BrowserWindow; +class SettingsMessage; class SettingsWindow; @@ -51,7 +51,6 @@ public: virtual bool QuitRequested(); private: - bool _OpenSettingsFile(BFile& file, uint32 mode); void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, @@ -65,6 +64,8 @@ private: BMessage* fLaunchRefsMessage; bool fInitialized; + SettingsMessage* fSettings; + DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 77364539fe..42c4492883 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -40,6 +40,8 @@ #include #include +#include "SettingsMessage.h" + enum { MSG_OK = 'aply', @@ -48,10 +50,11 @@ enum { }; -SettingsWindow::SettingsWindow(BRect frame) +SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + fSettings(settings) { SetLayout(new BGroupLayout(B_VERTICAL)); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 22ff3f7c10..76b215b03e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,11 +30,13 @@ #include class BButton; +class SettingsMessage; class SettingsWindow : public BWindow { public: - SettingsWindow(BRect frame); + SettingsWindow(BRect frame, + SettingsMessage* settings); virtual ~SettingsWindow(); virtual void MessageReceived(BMessage* message); @@ -45,6 +47,8 @@ private: void _RevertSettings(); private: + SettingsMessage* fSettings; + BButton* fOkButton; BButton* fCancelButton; BButton* fRevertButton; From 5c2095b4b08c8ccbc8ad97a1a2cf30c241b979ea Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 4 Mar 2010 18:17:24 +0000 Subject: [PATCH 099/293] * Link against liblocale.so and load app catalog. * Took FontSelectionView from Haiku Fonts preflet, but almost rewrote it to adapt for WebPositive needs. It's now a BHandler, so that it can actually receive messages itself. The Fonts version is a BView which is never attached, and only receives messages, because the window forwards them. Implemented option to use separate style menu. * Provide font settings in the Settings window. * Wired everything to make it work, although I am not sure standard font is applied. It does work for the serif font, though. Maybe I ought to install more fonts and check with simpler HTML. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@284 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 + src/apps/webpositive/BrowserApp.h | 3 + src/apps/webpositive/SettingsWindow.cpp | 243 ++++++++- src/apps/webpositive/SettingsWindow.h | 22 +- .../webpositive/support/FontSelectionView.cpp | 489 ++++++++++++++++++ .../webpositive/support/FontSelectionView.h | 83 +++ .../webpositive/support/SettingsMessage.cpp | 51 +- .../webpositive/support/SettingsMessage.h | 5 + 8 files changed, 883 insertions(+), 15 deletions(-) create mode 100644 src/apps/webpositive/support/FontSelectionView.cpp create mode 100644 src/apps/webpositive/support/FontSelectionView.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index aaffc30a1e..89bd3aeaeb 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ BrowserApp::BrowserApp() fDownloadWindow(NULL), fSettingsWindow(NULL) { + be_locale->GetAppCatalog(&fAppCatalog); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 531a88ffe0..d4fb9fbf59 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -30,6 +30,7 @@ #include +#include #include class DownloadWindow; @@ -68,6 +69,8 @@ private: DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; + + BCatalog fAppCatalog; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 42c4492883..906a029dfb 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -26,62 +26,133 @@ */ #include "SettingsWindow.h" -#include "BrowserApp.h" -#include "WebSettings.h" - #include #include #include #include #include #include +#include +#include +#include #include #include #include +#include #include +#include "BrowserApp.h" +#include "FontSelectionView.h" #include "SettingsMessage.h" +#include "WebSettings.h" +#undef TR_CONTEXT +#define TR_CONTEXT "Settings Window" + enum { - MSG_OK = 'aply', - MSG_CANCEL = 'cncl', - MSG_REVERT = 'rvrt', + MSG_APPLY = 'aply', + MSG_CANCEL = 'cncl', + MSG_REVERT = 'rvrt', + MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', + MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', }; +static const int32 kDefaultFontSize = 14; + SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : - BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + BWindow(frame, TR("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)); - fOkButton = new BButton("OK", new BMessage(MSG_OK)); + fStandardFontView = new FontSelectionView("standard", "Standard font:", + true, be_plain_font); + BFont defaultSerifFont = _FindDefaultSerifFont(); + fSerifFontView = new FontSelectionView("serif", "Serif font:", true, + &defaultSerifFont); + fSansSerifFontView = new FontSelectionView("sans serif", "Sans serif font:", + true, be_plain_font); + fFixedFontView = new FontSelectionView("fixed", "Fixed font:", true, + be_fixed_font); + + fStandardSizesMenu = new BMenuField("standard font size", + TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + + fFixedSizesMenu = new BMenuField("fixed font size", + TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); + + fApplyButton = new BButton("Apply", new BMessage(MSG_APPLY)); fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); float spacing = be_control_look->DefaultItemSpacing(); AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(BGridLayoutBuilder(spacing, spacing) + .Add(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) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .Add(fRevertButton) .AddGlue() .Add(fCancelButton) - .Add(fOkButton) + .Add(fApplyButton) .SetInsets(spacing, spacing, spacing, spacing) ) ); - fOkButton->MakeDefault(true); + AddHandler(fStandardFontView); + fStandardFontView->AttachedToLooper(); + + AddHandler(fSerifFontView); + fSerifFontView->AttachedToLooper(); + + AddHandler(fSansSerifFontView); + fSansSerifFontView->AttachedToLooper(); + + AddHandler(fFixedFontView); + fFixedFontView->AttachedToLooper(); + + fApplyButton->MakeDefault(true); if (!frame.IsValid()) CenterOnScreen(); + // load settings from disk + _RevertSettings(); + // apply to WebKit + _ApplySettings(); + // Start hidden Hide(); Show(); @@ -90,6 +161,14 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) SettingsWindow::~SettingsWindow() { + RemoveHandler(fStandardFontView); + delete fStandardFontView; + RemoveHandler(fSerifFontView); + delete fSerifFontView; + RemoveHandler(fSansSerifFontView); + delete fSansSerifFontView; + RemoveHandler(fFixedFontView); + delete fFixedFontView; } @@ -97,9 +176,8 @@ void SettingsWindow::MessageReceived(BMessage* message) { switch (message->what) { - case MSG_OK: + case MSG_APPLY: _ApplySettings(); - PostMessage(B_QUIT_REQUESTED); break; case MSG_CANCEL: _RevertSettings(); @@ -108,6 +186,20 @@ SettingsWindow::MessageReceived(BMessage* message) 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); + break; + } + case MSG_FIXED_FONT_SIZE_SELECTED: { + int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); + fFixedFontView->SetSize(size); + break; + } + default: BWindow::MessageReceived(message); break; @@ -124,18 +216,143 @@ SettingsWindow::QuitRequested() } +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 void SettingsWindow::_ApplySettings() { + // Store 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); + + 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); + + // This will find all currently instantiated page settings and apply + // the default values, unless the page settings have local overrides. + BWebSettings::Default()->Apply(); } void SettingsWindow::_RevertSettings() { + 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); } +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::_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) +{ + 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; +} diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 76b215b03e..9a6b7d9373 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,6 +30,9 @@ #include class BButton; +class BMenu; +class BMenuField; +class FontSelectionView; class SettingsMessage; @@ -42,16 +45,33 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + virtual void Show(); + private: void _ApplySettings(); void _RevertSettings(); + void _BuildSizesMenu(BMenu* menu, + uint32 messageWhat); + void _SetSizesMenuValue(BMenu* menu, int32 value); + int32 _SizesMenuValue(BMenu* menu); + + BFont _FindDefaultSerifFont() const; + private: SettingsMessage* fSettings; - BButton* fOkButton; + FontSelectionView* fStandardFontView; + FontSelectionView* fSerifFontView; + FontSelectionView* fSansSerifFontView; + FontSelectionView* fFixedFontView; + + BButton* fApplyButton; BButton* fCancelButton; BButton* fRevertButton; + + BMenuField* fStandardSizesMenu; + BMenuField* fFixedSizesMenu; }; diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp new file mode 100644 index 0000000000..038f0cdacb --- /dev/null +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -0,0 +1,489 @@ +/* + * Copyright 2001-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Mark Hogben + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Philippe Saint-Pierre, stpere@gmail.com + * Stephan Aßmus + */ + +#include "FontSelectionView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef TR_CONTEXT +#define TR_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) +{ + 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, NULL); + fFontsMenuField->SetFont(be_bold_font); + + // styles menu, if desired + if (separateStyles) { + fStylesMenu = new BPopUpMenu("styles menu"); + fStylesMenuField = new BMenuField("styles", TR("Style:"), fStylesMenu, + NULL); + } else { + fStylesMenu = NULL; + fStylesMenuField = NULL; + } + + // size menu + fSizesMenuField = new BMenuField("size", TR("Size:"), fSizesMenu, NULL); + fSizesMenuField->SetAlignment(B_ALIGN_RIGHT); + + // preview + fPreviewText = new BStringView("preview text", + TR_CMT("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->SetFont(&fCurrentFont); + 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); +} + + +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; +} + + +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(); + 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()); + } + 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(); + break; + } + + default: + BHandler::MessageReceived(message); + } +} + + +// #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(¤tFamily, ¤tStyle); + + 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 + + +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); + } +} + diff --git a/src/apps/webpositive/support/FontSelectionView.h b/src/apps/webpositive/support/FontSelectionView.h new file mode 100644 index 0000000000..f25801a840 --- /dev/null +++ b/src/apps/webpositive/support/FontSelectionView.h @@ -0,0 +1,83 @@ +/* + * Copyright 2001-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Mark Hogben + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Philippe Saint-Pierre, stpere@gmail.com + * Stephan Aßmus + */ +#ifndef FONT_SELECTION_VIEW_H +#define FONT_SELECTION_VIEW_H + + +#include +#include + +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 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: + 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; +}; + +#endif // FONT_SELECTION_VIEW_H diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index dad98820b2..7c2edddfc5 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008, Stephan Aßmus . + * Copyright 2008-2010, Stephan Aßmus . * Copyright 1998, Eric Shepherd. * All rights reserved. Distributed under the terms of the Be Sample Code * license. @@ -203,8 +203,31 @@ SettingsMessage::SetValue(const char* name, const BFlattenable* value) } +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); + } + return ret; +} + + // #pragma mark - + bool SettingsMessage::GetValue(const char* name, bool defaultValue) const { @@ -334,3 +357,29 @@ SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const 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; +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index f98121b5bb..85a29320b8 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -8,6 +8,7 @@ #define SETTINGS_MESSAGE_H #include +#include #include #include @@ -43,6 +44,8 @@ public: 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; @@ -70,6 +73,8 @@ public: const entry_ref& defaultValue) const; BMessage GetValue(const char* name, const BMessage& defaultValue) const; + BFont GetValue(const char* name, + const BFont& defaultValue) const; private: BPath fPath; From 0fe64862b7c900e74058496e7fe439ded4a18f3d Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 4 Mar 2010 19:35:26 +0000 Subject: [PATCH 100/293] Changed how auto-completion fills the choices. It doesn't remove choices with the same base URL anymore, but simply uses a lower priority for every less recent choice with the same base URL, and then sorts the result list after fetching. Previously, you would only get one choice for a given base URL, and that one was more likely a longer URL, since it was visited more recently than the start page of the respective site. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@286 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 51 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index fc01924a22..46b04fed51 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -94,6 +94,34 @@ layoutItemFor(BView* view) } +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) { @@ -110,6 +138,7 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { return; BString lastBaseURL; + int32 priority = INT_MAX; count = history->countItems(); for (int32 i = 0; i < count; i++) { @@ -120,17 +149,20 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { continue; if (lastBaseURL.Length() > 0 && choiceText.FindFirst(lastBaseURL) >= 0) { - continue; - } + priority--; + } else + priority = INT_MAX; int32 baseURLStart = choiceText.FindFirst("://") + 3; int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); lastBaseURL.SetTo(choiceText.String() + baseURLStart, baseURLEnd - baseURLStart); - fChoices.AddItem(new BAutoCompleter::Choice(choiceText, - choiceText, matchPos, pattern.Length())); + fChoices.AddItem(new URLChoice(choiceText, + choiceText, matchPos, pattern.Length(), priority)); } history->Unlock(); + + fChoices.SortItems(_CompareChoices); } virtual int32 CountChoices() const @@ -144,6 +176,17 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { fChoices.ItemAt(index)); } + static int _CompareChoices(const void* a, const void* b) + { + const URLChoice* aChoice = *reinterpret_cast(a); + const URLChoice* bChoice = *reinterpret_cast(b); + if (*aChoice < *bChoice) + return -1; + else if (*aChoice == *bChoice) + return 0; + return 1; + } + private: BList fChoices; }; From c108caf8653bd06bbf2dc98b22807178f0c3b652 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 6 Mar 2010 12:41:48 +0000 Subject: [PATCH 101/293] * Use a different deletion strategy for the BWebView. Since the BWebPage will delete itself in the application thread, we cannot delete the BWebView before this happens in the window thread. Now BWebPage is repsonsible for deleting the view. * Also make sure that there are not still loaders running on the frame. Since the timer messages arrive in a different handler than the BWebPage handler, the timer functions being called could operate on stale pointers. I am not sure why WebCore doesn't make sure of this itself. Perhaps we are not supposed to delete something directly, but via reference counting. Though I am not sure what it would be, since WebCore::Page is not reference countable. Maybe the frame... need to investigate. After all, there could be other timers in the queue besides loading related ones. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@295 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 16 ++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 46b04fed51..a2ff746a89 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -527,7 +527,7 @@ BrowserWindow::MessageReceived(BMessage* message) int32 index; if (message->FindInt32("tab index", &index) != B_OK) index = fTabManager->SelectedTabIndex(); - delete fTabManager->RemoveTab(index); + _ShutdownTab(index); _UpdateTabGroupVisibility(); } else PostMessage(B_QUIT_REQUESTED); @@ -581,7 +581,7 @@ BrowserWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. while (fTabManager->CountTabs() > 0) - delete fTabManager->RemoveTab(0L); + _ShutdownTab(0); SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -900,3 +900,15 @@ BrowserWindow::_UpdateTabGroupVisibility() Unlock(); } } + + +void +BrowserWindow::_ShutdownTab(int32 index) +{ + BView* view = fTabManager->RemoveTab(index); + BWebView* webView = dynamic_cast(view); + if (webView) + webView->Shutdown(); + else + delete view; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0fafb1ec2e..e52048f128 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -118,6 +118,7 @@ private: private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); + void _ShutdownTab(int32 index); private: BMessenger fDownloadListener; From 6faa5c3d74ae9ab65827194b88ba910dc83c301c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 9 Mar 2010 09:26:44 +0000 Subject: [PATCH 102/293] Use the "bytes" member from the keydown message in order to get mapped keys. The 8 and 2 on the number pad would not work in the URL bar otherwise, since those map to "B_UP_ARROW" and "B_DOWN_ARROW" as raw char. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@302 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/TextControlCompleter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp index 6b3c257602..552c8b5f5d 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -85,13 +85,14 @@ TextControlCompleter::~TextControlCompleter() filter_result TextControlCompleter::Filter(BMessage* message, BHandler** target) { - int32 rawChar, modifiers; - if (!target || message->FindInt32("raw_char", &rawChar) != B_OK + const char* bytes; + int32 modifiers; + if (!target || message->FindString("bytes", &bytes) != B_OK || message->FindInt32("modifiers", &modifiers) != B_OK) { return B_DISPATCH_MESSAGE; } - switch (rawChar) { + switch (bytes[0]) { case B_UP_ARROW: SelectPrevious(); return B_SKIP_MESSAGE; From 7239ea752d0486bed93d1c3e97c26a8556822362 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 9 Mar 2010 11:49:34 +0000 Subject: [PATCH 103/293] * Added a class CookieJarClient to WebCore's CookieJar.h which provides the same functionality as the global methods for managing cookies. This is only enabled for the Haiku platform. Since the global cookie methods get a Document pointer, I envision, the CookieJarClient could eventually be a member of Document instances. It would then be passed upon WebCore::Page creation. Still waiting on feedback from other WebKit developers on this one. This change is more elegant than what the Qt port does, which is to use WebKit classes in WebCore (layering violation). Right now, a single global instance of a CookieJarClient can be assigned. * Implemented CookieJarClientHaiku which uses a BNetworkCookieJar to forward the requests. Eventually, the behaviour could be browser specific. * Added all the necessary wiring to BrowserApplication to make the cookie jar persistent. * TODO: Actually parse cookies and handle at least the expiration date, but other stuff like matching the domain of the cookie and the URL and "HTTP-only" cookies seems important as well. Even though I have confirmed that cookies are stored and restored correctly, and also retrieved via the global cookie methods, I can see no change in browser behaviour. For example enabling "Stay signed in" on googlemail.com does not work in WebPositive, although BeZillaBrowser automatically logs in in a new session when surfing to googlemail.com. No idea if this is even implemented with cookies, although it seems like it should be. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@303 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 16 ++++++++++++++++ src/apps/webpositive/BrowserApp.h | 3 +++ src/apps/webpositive/BrowserWindow.cpp | 14 ++++++-------- src/apps/webpositive/support/SettingsMessage.cpp | 6 +++--- src/apps/webpositive/support/SettingsMessage.h | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 89bd3aeaeb..29fe7b6ccd 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -34,6 +34,7 @@ #include "DownloadWindow.h" #include "SettingsMessage.h" #include "SettingsWindow.h" +#include "NetworkCookieJar.h" #include "WebPage.h" #include "WebSettings.h" #include "WebView.h" @@ -61,6 +62,7 @@ BrowserApp::BrowserApp() fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), + fCookieJar(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) { @@ -72,6 +74,8 @@ BrowserApp::~BrowserApp() { delete fLaunchRefsMessage; delete fSettings; + delete fCookies; + delete fCookieJar; } @@ -125,6 +129,14 @@ BrowserApp::ReadyToRun() mainSettingsPath << "/Application"; fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, mainSettingsPath.String()); + 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); fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", @@ -261,6 +273,10 @@ BrowserApp::QuitRequested() fSettingsWindow->Unlock(); } + BMessage cookieArchive; + if (fCookieJar->Archive(&cookieArchive) == B_OK) + fCookies->SetValue("cookies", cookieArchive); + return true; } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index d4fb9fbf59..dfc9433e5e 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -33,6 +33,7 @@ #include #include +class BNetworkCookieJar; class DownloadWindow; class BrowserWindow; class SettingsMessage; @@ -66,6 +67,8 @@ private: bool fInitialized; SettingsMessage* fSettings; + SettingsMessage* fCookies; + BNetworkCookieJar* fCookieJar; DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a2ff746a89..4b0ef6b758 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -197,10 +197,11 @@ private: BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) - : BWebWindow(frame, kApplicationName, + : + BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) - , fDownloadListener(downloadListener) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fDownloadListener(downloadListener) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -346,11 +347,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStatusText = 0; fLoadingProgressBar = 0; - BWebView* webView = new BWebView("web_view"); - SetCurrentWebView(webView); - - AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(CurrentWebView()) + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(fTabManager->ContainerView()) ); } diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index 7c2edddfc5..98e9ef1c94 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -186,11 +186,11 @@ SettingsMessage::SetValue(const char* name, const entry_ref& value) status_t -SettingsMessage::SetValue(const char* name, const BMessage* value) +SettingsMessage::SetValue(const char* name, const BMessage& value) { - if (ReplaceMessage(name, value) == B_OK) + if (ReplaceMessage(name, &value) == B_OK) return B_OK; - return AddMessage(name, value); + return AddMessage(name, &value); } diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index 85a29320b8..8420238be8 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -41,7 +41,7 @@ public: 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); + const BMessage& value); status_t SetValue(const char* name, const BFlattenable* value); status_t SetValue(const char* name, From dcad381777abe240b6c4ce4a2da9f1dd445e4b0c Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Mar 2010 14:10:14 +0000 Subject: [PATCH 104/293] Bugfixes for tab view click events: * When adding/removing tabs, process a fake mouse moved event to synchronize with the new tab layout. * Count the mouse clicks for the "double click into empty area opens new tab" feature in such a way that clicks into tabs never count (closing a tab was the first click before, the second would immediately open a new tab and similar issues). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@309 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 78 +++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 4dbb0bfc70..9f40c9aeef 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -111,7 +111,7 @@ private: private: TabContainerView* fContainerView; TabLayoutItem* fLayoutItem; - + BString fLabel; bool fIsFirst; @@ -145,6 +145,8 @@ public: 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); @@ -159,10 +161,13 @@ public: private: TabView* _TabAt(const BPoint& where) const; + void _MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); private: TabView* fLastMouseEventTab; bool fMouseDown; + uint32 fClickCount; TabView* fSelectedTab; Controller* fController; }; @@ -179,6 +184,7 @@ TabContainerView::TabContainerView(Controller* controller) BGroupView(B_HORIZONTAL), fLastMouseEventTab(NULL), fMouseDown(false), + fClickCount(0), fSelectedTab(NULL), fController(controller) { @@ -260,8 +266,12 @@ TabContainerView::MouseDown(BPoint where) SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); if (fLastMouseEventTab) fLastMouseEventTab->MouseDown(where, buttons); - else if (clicks > 1) - fController->DoubleClickOutsideTabs(); + else { + if (clicks > 1) + fClickCount++; + else + fClickCount = 1; + } } @@ -271,6 +281,10 @@ TabContainerView::MouseUp(BPoint where) fMouseDown = false; if (fLastMouseEventTab) fLastMouseEventTab->MouseUp(where); + else if (fClickCount > 1) { + fClickCount = 0; + fController->DoubleClickOutsideTabs(); + } } @@ -278,27 +292,22 @@ 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 && 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); - } + _MouseMoved(where, transit, dragMessage); } +void +TabContainerView::DoLayout() +{ + BGroupView::DoLayout(); + + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons, false); + if (Bounds().Contains(where)) + _MouseMoved(where, B_INSIDE_VIEW, NULL); +} + void TabContainerView::AddTab(const char* label, int32 index) { @@ -416,7 +425,7 @@ TabContainerView::SelectTab(int32 index) GroupLayout()->ItemAt(index)); if (item) tab = item->Parent(); - + SelectTab(tab); } @@ -472,6 +481,31 @@ TabContainerView::_TabAt(const BPoint& where) const } +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 && 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); + } +} + + // #pragma mark - TabView From 88e373028cbb4d49b0098b89e1c26e1a92966e9b Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 14 Mar 2010 10:27:39 +0000 Subject: [PATCH 105/293] * Made BWebPage download related methods and listener member static. * Introduced BWebPage::RequestDownload() public API (expected to run synchronous). * Added necessary wiring for "Download this link" in context menus. * Restarting downloads works in principle, although with some quirks. (Sometimes it appears the "Desktop" is being downloaded...) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@310 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 10 +++++----- src/apps/webpositive/BrowserWindow.cpp | 13 +++++-------- src/apps/webpositive/BrowserWindow.h | 2 -- src/apps/webpositive/DownloadWindow.cpp | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 29fe7b6ccd..e4b4c10d15 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -124,7 +124,7 @@ BrowserApp::ReadyToRun() BWebSettings::SetPersistentStoragePath(path.Path()); } - + BString mainSettingsPath(kApplicationName); mainSettingsPath << "/Application"; fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, @@ -148,6 +148,8 @@ BrowserApp::ReadyToRun() fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); + BWebPage::SetDownloadListener(BMessenger(fDownloadWindow)); + fInitialized = true; if (fLaunchRefsMessage) { @@ -155,8 +157,7 @@ BrowserApp::ReadyToRun() delete fLaunchRefsMessage; fLaunchRefsMessage = 0; } else { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, - BMessenger(fDownloadWindow)); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -313,8 +314,7 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, - BMessenger(fDownloadWindow)); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame); window->Show(); if (url.Length()) window->CurrentWebView()->LoadURL(url.String()); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b0ef6b758..6f09e9bc74 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -195,13 +195,11 @@ private: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy toolbarPolicy) +BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), - fDownloadListener(downloadListener) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -373,7 +371,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); } - + be_app->PostMessage(WINDOW_OPENED); } @@ -538,7 +536,7 @@ BrowserWindow::MessageReceived(BMessage* message) && fTabManager->CountTabs() > index) { fTabManager->SelectTab(index); } - + break; } @@ -629,7 +627,6 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) // Executed in app thread (new BWebPage needs to be created in app thread). if (!webView) webView = new BWebView("web view"); - webView->WebPage()->SetDownloadListener(fDownloadListener); fTabManager->AddTab(webView, "New tab"); @@ -675,7 +672,7 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) } -void +void BrowserWindow::NewPageCreated(BWebView* view) { CreateNewTab(BString(), true, view); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e52048f128..0b2c4788ea 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -66,7 +66,6 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, - const BMessenger& downloadListener, ToolbarPolicy = HaveToolbar); virtual ~BrowserWindow(); @@ -121,7 +120,6 @@ private: void _ShutdownTab(int32 index); private: - BMessenger fDownloadListener; BMenu* fGoMenu; IconButton* fBackButton; IconButton* fForwardButton; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 44e5fa936e..60d9701e9b 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -257,7 +257,7 @@ public: break; } case RESTART_DOWNLOAD: - // TODO: + BWebPage::RequestDownload(m_url); break; case CANCEL_DOWNLOAD: From e509fd60c14849be0d9bc390f0761149fab42985 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 13:04:01 +0000 Subject: [PATCH 106/293] Added code for bookmarking the current page and opening the Bookmarks folder in Tracker (or the preferred file manager). Populating the Bookmarks menu is still missing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@314 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 149 +++++++++++++++++++++++++ src/apps/webpositive/BrowserWindow.h | 6 + 2 files changed, 155 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 6f09e9bc74..1bc8e407cc 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -47,13 +47,18 @@ #include #include #include +#include #include +#include +#include #include #include #include #include #include +#include #include +#include #include #include #include @@ -72,6 +77,9 @@ enum { RELOAD = 'reld', CLEAR_HISTORY = 'clhs', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', + TEXT_SIZE_INCREASE = 'tsin', TEXT_SIZE_DECREASE = 'tsdc', TEXT_SIZE_RESET = 'tsrs', @@ -247,6 +255,14 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) fGoMenu = new BMenu("Go"); mainMenu->AddItem(fGoMenu); + fBookmarkMenu = new BMenu("Bookmarks"); + fBookmarkMenu->AddItem(new BMenuItem("Bookmark this page", + new BMessage(CREATE_BOOKMARK), 'B')); + fBookmarkMenu->AddItem(new BMenuItem("Manage bookmarks", + new BMessage(SHOW_BOOKMARKS))); +// fBookmarkMenu->AddSeparatorItem(); + mainMenu->AddItem(fBookmarkMenu); + // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); fBackButton->SetIcon(201); @@ -458,6 +474,13 @@ BrowserWindow::MessageReceived(BMessage* message) break; } + case CREATE_BOOKMARK: + _CreateBookmark(); + break; + case SHOW_BOOKMARKS: + _ShowBookmarks(); + break; + case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one @@ -907,3 +930,129 @@ BrowserWindow::_ShutdownTab(int32 index) else delete view; } + + +status_t +BrowserWindow::_BookmarkPath(BPath& path) const +{ + status_t ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (ret != B_OK) + return ret; + + ret = path.Append(kApplicationName); + if (ret != B_OK) + return ret; + + ret = path.Append("Bookmarks"); + if (ret != B_OK) + return ret; + + return create_directory(path.Path(), 0777); +} + + +void +BrowserWindow::_CreateBookmark() +{ + BPath path; + status_t status = _BookmarkPath(path); + if (status != B_OK) { + BString message("There was an error retrieving the bookmark " + "folder.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } + BWebView* webView = CurrentWebView(); + BString url(webView->MainFrameURL()); + // Create a bookmark file + BFile bookmarkFile; + BString bookmarkName(webView->MainFrameTitle()); + BPath entryPath(path); + status = entryPath.Append(bookmarkName); + BEntry entry; + if (status == B_OK) + status = entry.SetTo(entryPath.Path(), true); + if (status == B_OK) { + if (entry.Exists()) { + BString storedURL; + if (bookmarkFile.SetTo(&entry, B_READ_ONLY) == B_OK + && bookmarkFile.ReadAttrString("META:url", + &storedURL) == B_OK) { + // Just bail if the bookmark already exists + if (storedURL == url) { + BString message("A bookmark for this page ("); + message << webView->MainFrameTitle(); + message << ") already exists."; + BAlert* alert = new BAlert("Bookmark info", + message.String(), "OK"); + alert->Go(); + return; + } + } + } + int32 tries = 1; + while (entry.Exists()) { + // Find a unique name for the bookmark + bookmarkName = webView->MainFrameTitle(); + bookmarkName << " " << tries++; + entryPath = path; + status = entryPath.Append(bookmarkName); + if (status == B_OK) + status = entry.SetTo(entryPath.Path(), true); + if (status != B_OK) + break; + } + } + if (status == B_OK) { + status = bookmarkFile.SetTo(&entry, + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); + } + + if (status == B_OK) + status = bookmarkFile.WriteAttrString("META:url", &url); + if (status == B_OK) { + BString title = webView->MainFrameTitle(); + bookmarkFile.WriteAttrString("META:title", &title); + } + + BNodeInfo nodeInfo(&bookmarkFile); + if (status == B_OK) + status = nodeInfo.SetType("application/x-vnd.Be-bookmark"); + + if (status != B_OK) { + BString message("There was an error creating the bookmark " + "file.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } +} + + +void +BrowserWindow::_ShowBookmarks() +{ + BPath path; + entry_ref ref; + status_t status = _BookmarkPath(path); + if (status == B_OK) + status = get_ref_for_path(path.Path(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + + if (status != B_OK && status != B_ALREADY_RUNNING) { + BString message("There was an error trying to show the Bookmarks " + "folder.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0b2c4788ea..caa53b4571 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -38,6 +38,7 @@ class BButton; class BCheckBox; class BLayoutItem; class BMenu; +class BPath; class BStatusBar; class BStringView; class BTextControl; @@ -119,8 +120,13 @@ private: void _UpdateTabGroupVisibility(); void _ShutdownTab(int32 index); + status_t _BookmarkPath(BPath& path) const; + void _CreateBookmark(); + void _ShowBookmarks(); + private: BMenu* fGoMenu; + BMenu* fBookmarkMenu; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From 3760e5d86812dedd42fc9bcb0b2abfad9f65255c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 13:49:35 +0000 Subject: [PATCH 107/293] * Added Tracker Kit NavMenu.h and SlowMenu.h which ought to be removed when WebPositive is moved into the Haiku repo. * Convert the Bookmarks menu into a BNavMenu, make sure it updates to the current folder contens each time it opens. * Wire everything to complete the bookmark support. Managing bookmarks is fairly nice by re-using Tracker. One can even put anything into the book mark folder and WebPositive will launch the respective app if it doesn't have a META:url attribute. The most immediate benefit is that clicking sub-folders in the Bookmarks folder will also open that folder in Tracker. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@315 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 66 +++++++++- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/support/NavMenu.h | 168 ++++++++++++++++++++++++ src/apps/webpositive/support/SlowMenu.h | 76 +++++++++++ 4 files changed, 303 insertions(+), 8 deletions(-) create mode 100644 src/apps/webpositive/support/NavMenu.h create mode 100644 src/apps/webpositive/support/SlowMenu.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 1bc8e407cc..4d13b7eac8 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" +#include "NavMenu.h" #include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" @@ -200,6 +201,31 @@ private: }; +class BookmarkMenu : public BNavMenu { +public: + BookmarkMenu(const char* title, BHandler* target, const entry_ref* navDir) + : + BNavMenu(title, B_REFS_RECEIVED, target) + { + SetNavDir(navDir); + } + + virtual void AttachedToWindow() + { + RemoveItems(0, CountItems(), true); + ForceRebuild(); + BNavMenu::AttachedToWindow(); + if (CountItems() > 0) + AddItem(new BSeparatorItem(), 0); + AddItem(new BMenuItem("Manage bookmarks", + new BMessage(SHOW_BOOKMARKS)), 0); + AddItem(new BMenuItem("Bookmark this page", + new BMessage(CREATE_BOOKMARK), 'B'), 0); + DoLayout(); + } +}; + + // #pragma mark - BrowserWindow @@ -255,13 +281,14 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) fGoMenu = new BMenu("Go"); mainMenu->AddItem(fGoMenu); - fBookmarkMenu = new BMenu("Bookmarks"); - fBookmarkMenu->AddItem(new BMenuItem("Bookmark this page", - new BMessage(CREATE_BOOKMARK), 'B')); - fBookmarkMenu->AddItem(new BMenuItem("Manage bookmarks", - new BMessage(SHOW_BOOKMARKS))); -// fBookmarkMenu->AddSeparatorItem(); - mainMenu->AddItem(fBookmarkMenu); + BPath bookmarkPath; + entry_ref bookmarkRef; + if (_BookmarkPath(bookmarkPath) == B_OK + && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { + BMenu* bookmarkMenu + = new BookmarkMenu("Bookmarks", this, &bookmarkRef); + mainMenu->AddItem(bookmarkMenu); + } // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); @@ -481,6 +508,31 @@ BrowserWindow::MessageReceived(BMessage* message) _ShowBookmarks(); break; + case B_REFS_RECEIVED: { + // Currently only source of these messages is the bookmarks menu. + // Filter refs into urls, this also gets rid of refs for folders. + // For clicks on sub-folders in the bookmarks menu, we have Tracker + // open the corresponding folder. + entry_ref ref; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BFile file(&ref, B_READ_ONLY); + bool isURL = false; + if (file.InitCheck() == B_OK) { + BString url; + if (file.ReadAttrString("META:url", &url) == B_OK) { + message->AddString("url", url.String()); + isURL = true; + } + } + if (!isURL) { + // Must be a folder or something else, have the system open it. + be_roster->Launch(&ref); + } + } + message->RemoveName("refs"); + be_app->PostMessage(message); + break; + } case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index caa53b4571..5def1c05ee 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -126,7 +126,6 @@ private: private: BMenu* fGoMenu; - BMenu* fBookmarkMenu; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; diff --git a/src/apps/webpositive/support/NavMenu.h b/src/apps/webpositive/support/NavMenu.h new file mode 100644 index 0000000000..127d94f255 --- /dev/null +++ b/src/apps/webpositive/support/NavMenu.h @@ -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 +#include +#include + +#include "SlowMenu.h" + + +template 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 *list = NULL); + BNavMenu(const char* title, uint32 message, const BMessenger &, + BWindow *parentWindow = NULL, const BObjectList *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 *list); + const BObjectList *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 *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 *fItemList; + EntryListBase *fContainer; + bool fIteratingDesktop; + + const BObjectList *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 *typeslist); +_IMPEXP_TRACKER void SpringLoadedFolderAddUniqueTypeToList(entry_ref *ref, + BObjectList *typeslist); +_IMPEXP_TRACKER void SpringLoadedFolderCacheDragData(const BMessage *incoming, + BMessage **, BObjectList **typeslist); + +} // namespace BPrivate + +using namespace BPrivate; + +#endif // NAV_MENU_H diff --git a/src/apps/webpositive/support/SlowMenu.h b/src/apps/webpositive/support/SlowMenu.h new file mode 100644 index 0000000000..62e9156b07 --- /dev/null +++ b/src/apps/webpositive/support/SlowMenu.h @@ -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 +#include +#include + +// 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__ */ From c1f8fe4de1aeebf5829a597bed88f3f2ca4900cd Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 18:08:30 +0000 Subject: [PATCH 108/293] Improvements in bookmark handling: * Search for existing bookmarks recursively. * Open all bookmarks at once, when the user clicks a bookmark folder in the menu (thanks Axel). But do ask for confirmation if there are more than ten bookmarks. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@318 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 144 ++++++++++++++++++++----- src/apps/webpositive/BrowserWindow.h | 11 ++ 2 files changed, 128 insertions(+), 27 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4d13b7eac8..0a5d2f6940 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -509,27 +509,48 @@ BrowserWindow::MessageReceived(BMessage* message) break; case B_REFS_RECEIVED: { - // Currently only source of these messages is the bookmarks menu. - // Filter refs into urls, this also gets rid of refs for folders. + // Currently the only source of these messages is the bookmarks menu. + // Filter refs into URLs, this also gets rid of refs for folders. // For clicks on sub-folders in the bookmarks menu, we have Tracker // open the corresponding folder. entry_ref ref; + uint32 addedCount = 0; for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { - BFile file(&ref, B_READ_ONLY); - bool isURL = false; - if (file.InitCheck() == B_OK) { +printf("B_REFS_RECEIVED: %s\n", ref.name); + BEntry entry(&ref); + uint32 addedSubCount = 0; + if (entry.IsDirectory()) { + BDirectory directory(&entry); +printf(" directory ok\n"); + _AddBookmarkURLsRecursively(directory, message, addedSubCount); + } else { + BFile file(&ref, B_READ_ONLY); +printf(" file ok\n"); BString url; - if (file.ReadAttrString("META:url", &url) == B_OK) { + if (_ReadURLAttr(file, url)) { message->AddString("url", url.String()); - isURL = true; + addedSubCount++; } } - if (!isURL) { - // Must be a folder or something else, have the system open it. + if (addedSubCount == 0) { + // Don't know what to do with this entry, just pass it + // on to the system to handle. Note that this may result + // in us opening other supported files via the application + // mechanism. be_roster->Launch(&ref); } + addedCount += addedSubCount; } message->RemoveName("refs"); + if (addedCount > 10) { + BString string; + string << "Do you want to open " << addedCount; + string << " bookmarks all at once?"; + BAlert* alert = new BAlert("Open bookmarks confirmation", + string.String(), "Cancel", "Open all"); + if (alert->Go() == 0) + break; + } be_app->PostMessage(message); break; } @@ -1022,32 +1043,36 @@ BrowserWindow::_CreateBookmark() // Create a bookmark file BFile bookmarkFile; BString bookmarkName(webView->MainFrameTitle()); + if (bookmarkName.Length() == 0) { + bookmarkName = url; + int32 leafPos = bookmarkName.FindLast('/'); + if (leafPos >= 0) + bookmarkName.Remove(0, leafPos + 1); + } + + // Check that the bookmark exists nowhere in the bookmark hierarchy, + // though the intended file name must match, we don't search the stored + // URLs, only for matching file names. + BDirectory directory(path.Path()); + if (status == B_OK && _CheckBookmarkExists(directory, bookmarkName, url)) { + BString message("A bookmark for this page ("); + message << bookmarkName; + message << ") already exists."; + BAlert* alert = new BAlert("Bookmark info", message.String(), "OK"); + alert->Go(); + return; + } + BPath entryPath(path); status = entryPath.Append(bookmarkName); BEntry entry; if (status == B_OK) status = entry.SetTo(entryPath.Path(), true); if (status == B_OK) { - if (entry.Exists()) { - BString storedURL; - if (bookmarkFile.SetTo(&entry, B_READ_ONLY) == B_OK - && bookmarkFile.ReadAttrString("META:url", - &storedURL) == B_OK) { - // Just bail if the bookmark already exists - if (storedURL == url) { - BString message("A bookmark for this page ("); - message << webView->MainFrameTitle(); - message << ") already exists."; - BAlert* alert = new BAlert("Bookmark info", - message.String(), "OK"); - alert->Go(); - return; - } - } - } int32 tries = 1; while (entry.Exists()) { - // Find a unique name for the bookmark + // Find a unique name for the bookmark, there may still be a + // file in the way that stores a different URL. bookmarkName = webView->MainFrameTitle(); bookmarkName << " " << tries++; entryPath = path; @@ -1063,6 +1088,7 @@ BrowserWindow::_CreateBookmark() B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); } + // Write bookmark meta data if (status == B_OK) status = bookmarkFile.WriteAttrString("META:url", &url); if (status == B_OK) { @@ -1108,3 +1134,67 @@ BrowserWindow::_ShowBookmarks() } } + +bool BrowserWindow::_CheckBookmarkExists(BDirectory& directory, + const BString& bookmarkName, const BString& url) const +{ + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + if (entry.IsDirectory()) { + BDirectory subBirectory(&entry); + // At least preserve the entry file handle when recursing into + // sub-folders... eventually we will run out, though, with very + // deep hierarchy. + entry.Unset(); + if (_CheckBookmarkExists(subBirectory, bookmarkName, url)) + return true; + } else { + char entryName[B_FILE_NAME_LENGTH]; + if (entry.GetName(entryName) != B_OK || bookmarkName != entryName) + continue; + BString storedURL; + BFile file(&entry, B_READ_ONLY); + if (_ReadURLAttr(file, storedURL)) { + // Just bail if the bookmark already exists + if (storedURL == url) + return true; + } + } + } + return false; +} + + +bool +BrowserWindow::_ReadURLAttr(BFile& bookmarkFile, BString& url) const +{ + return bookmarkFile.InitCheck() == B_OK + && bookmarkFile.ReadAttrString("META:url", &url) == B_OK; +} + + +void +BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, + BMessage* message, uint32& addedCount) const +{ + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + if (entry.IsDirectory()) { + BDirectory subBirectory(&entry); + // At least preserve the entry file handle when recursing into + // sub-folders... eventually we will run out, though, with very + // deep hierarchy. + entry.Unset(); + _AddBookmarkURLsRecursively(subBirectory, message, addedCount); + } else { + BString storedURL; + BFile file(&entry, B_READ_ONLY); + if (_ReadURLAttr(file, storedURL)) { + message->AddString("url", storedURL.String()); + addedCount++; + } + } + } +} + + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 5def1c05ee..4e6cac811c 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -36,6 +36,8 @@ class BButton; class BCheckBox; +class BDirectory; +class BFile; class BLayoutItem; class BMenu; class BPath; @@ -123,6 +125,15 @@ private: 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; private: BMenu* fGoMenu; From 193f6b806fc39c45f5760fa3918b01b79e8796fa Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:37:15 +0000 Subject: [PATCH 109/293] Small cleanup. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@321 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/FontSelectionView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 038f0cdacb..24fcd248fb 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -77,11 +77,11 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, fPreviewText = new BStringView("preview text", TR_CMT("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->SetFont(&fCurrentFont); 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(); } From e4b86f6ceb381edbf9f8358e7d248f97ab427785 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:38:23 +0000 Subject: [PATCH 110/293] * Improved API for more convenience. * Fixed comparison operators. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@322 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/DateTime.cpp | 178 +++++++++++++++++----- src/apps/webpositive/support/DateTime.h | 34 +++-- 2 files changed, 164 insertions(+), 48 deletions(-) diff --git a/src/apps/webpositive/support/DateTime.cpp b/src/apps/webpositive/support/DateTime.cpp index 7818dc36c2..19030db00a 100644 --- a/src/apps/webpositive/support/DateTime.cpp +++ b/src/apps/webpositive/support/DateTime.cpp @@ -38,7 +38,18 @@ const bigtime_t kMicrosecondsPerDay = 86400000000LL; but be aware IsValid() will return false. */ BTime::BTime() - : fMicroseconds(-1) + : + fMicroseconds(-1) +{ +} + + +/*! + Constructs a new BTime object as a copy of \c other. +*/ +BTime::BTime(const BTime& other) + : + fMicroseconds(other.fMicroseconds) { } @@ -51,7 +62,8 @@ BTime::BTime() specified time is invalid, the time is not set and IsValid() returns false. */ BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) - : fMicroseconds(-1) + : + fMicroseconds(-1) { _SetTime(hour, minute, second, microsecond); } @@ -61,7 +73,8 @@ BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) Constructs a new BTime object from the provided BMessage archive. */ BTime::BTime(const BMessage* archive) - : fMicroseconds(-1) + : + fMicroseconds(-1) { if (archive == NULL) return; @@ -192,10 +205,11 @@ BTime::SetTime(int32 hour, int32 minute, int32 second, int32 microsecond) Adds \c hours to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddHours(int32 hours) { - _AddMicroseconds(bigtime_t(hours % kHoursPerDay) * kMicrosecondsPerHour); + return _AddMicroseconds(bigtime_t(hours % kHoursPerDay) + * kMicrosecondsPerHour); } @@ -203,11 +217,11 @@ BTime::AddHours(int32 hours) Adds \c minutes to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMinutes(int32 minutes) { - _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) * - kMicrosecondsPerMinute); + return _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) + * kMicrosecondsPerMinute); } @@ -215,11 +229,11 @@ BTime::AddMinutes(int32 minutes) Adds \c seconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddSeconds(int32 seconds) { - _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) * - kMicrosecondsPerSecond); + return _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) + * kMicrosecondsPerSecond); } @@ -227,10 +241,11 @@ BTime::AddSeconds(int32 seconds) Adds \c milliseconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMilliseconds(int32 milliseconds) { - _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) * 1000); + return _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) + * 1000); } @@ -238,10 +253,10 @@ BTime::AddMilliseconds(int32 milliseconds) Adds \c microseconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMicroseconds(int32 microseconds) { - _AddMicroseconds(microseconds); + return _AddMicroseconds(microseconds); } @@ -396,7 +411,7 @@ BTime::operator>=(const BTime& time) const } -void +BTime& BTime::_AddMicroseconds(bigtime_t microseconds) { bigtime_t count = 0; @@ -405,6 +420,7 @@ BTime::_AddMicroseconds(bigtime_t microseconds) kMicrosecondsPerDay; } fMicroseconds = (_Microseconds() + microseconds + count) % kMicrosecondsPerDay; + return *this; } @@ -432,9 +448,22 @@ BTime::_SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, Constructs a new BDate object. IsValid() will return false. */ BDate::BDate() - : fDay(-1), - fYear(0), - fMonth(-1) + : + fDay(-1), + fYear(0), + fMonth(-1) +{ +} + + +/*! + Constructs a new BDate object as a copy of \c other. +*/ +BDate::BDate(const BDate& other) + : + fDay(other.fDay), + fYear(other.fYear), + fMonth(other.fMonth) { } @@ -458,9 +487,10 @@ BDate::BDate(int32 year, int32 month, int32 day) Constructs a new BDate object from the provided archive. */ BDate::BDate(const BMessage* archive) - : fDay(-1), - fYear(0), - fMonth(-1) + : + fDay(-1), + fYear(0), + fMonth(-1) { if (archive == NULL) return; @@ -863,13 +893,23 @@ BDate::DaysInMonth() const } +/*! + Returns the short day name of this object. +*/ +BString +BDate::ShortDayName() const +{ + return ShortDayName(DayOfWeek()); +} + + /*! Returns the short day name in case of an valid day, otherwise an empty string. The passed \c day must be in the range of 1 to 7 while 1 stands for monday. */ -BString -BDate::ShortDayName(int32 day) const +/*static*/ BString +BDate::ShortDayName(int32 day) { if (day < 1 || day > 7) return BString(); @@ -885,12 +925,22 @@ BDate::ShortDayName(int32 day) const } +/*! + Returns the short month name of this object. +*/ +BString +BDate::ShortMonthName() const +{ + return ShortMonthName(Month()); +} + + /*! Returns the short month name in case of an valid month, otherwise an empty string. The passed \c month must be in the range of 1 to 12. */ -BString -BDate::ShortMonthName(int32 month) const +/*static*/ BString +BDate::ShortMonthName(int32 month) { if (month < 1 || month > 12) return BString(); @@ -906,13 +956,23 @@ BDate::ShortMonthName(int32 month) const } +/*! + Returns the long day name of this object's week day. +*/ +BString +BDate::LongDayName() const +{ + return LongDayName(DayOfWeek()); +} + + /*! Returns the long day name in case of an valid day, otherwise an empty string. The passed \c day must be in the range of 1 to 7 while 1 stands for monday. */ -BString -BDate::LongDayName(int32 day) const +/*static*/ BString +BDate::LongDayName(int32 day) { if (day < 1 || day > 7) return BString(); @@ -928,12 +988,22 @@ BDate::LongDayName(int32 day) const } +/*! + Returns the long month name of this object's month. +*/ +BString +BDate::LongMonthName() const +{ + return LongMonthName(Month()); +} + + /*! Returns the long month name in case of an valid month, otherwise an empty string. The passed \c month must be in the range of 1 to 12. */ -BString -BDate::LongMonthName(int32 month) const +/*static*/ BString +BDate::LongMonthName(int32 month) { if (month < 1 || month > 12) return BString(); @@ -1218,7 +1288,17 @@ BDateTime::SetDateTime(const BDate& date, const BTime& time) /*! Returns the current date of this object. */ -BDate +BDate& +BDateTime::Date() +{ + return fDate; +} + + +/*! + Returns the current date of this object. +*/ +const BDate& BDateTime::Date() const { return fDate; @@ -1238,7 +1318,17 @@ BDateTime::SetDate(const BDate& date) /*! Returns the current time of this object. */ -BTime +BTime& +BDateTime::Time() +{ + return fTime; +} + + +/*! + Returns the current time of this object. +*/ +const BTime& BDateTime::Time() const { return fTime; @@ -1328,7 +1418,11 @@ BDateTime::operator==(const BDateTime& dateTime) const bool BDateTime::operator<(const BDateTime& dateTime) const { - return fTime < dateTime.fTime && fDate < dateTime.fDate; + if (fDate < dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime < dateTime.fTime; + return false; } @@ -1339,7 +1433,11 @@ BDateTime::operator<(const BDateTime& dateTime) const bool BDateTime::operator<=(const BDateTime& dateTime) const { - return fTime <= dateTime.fTime && fDate <= dateTime.fDate; + if (fDate < dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime <= dateTime.fTime; + return false; } @@ -1349,7 +1447,11 @@ BDateTime::operator<=(const BDateTime& dateTime) const bool BDateTime::operator>(const BDateTime& dateTime) const { - return fTime > dateTime.fTime && fDate > dateTime.fDate; + if (fDate > dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime > dateTime.fTime; + return false; } @@ -1360,7 +1462,11 @@ BDateTime::operator>(const BDateTime& dateTime) const bool BDateTime::operator>=(const BDateTime& dateTime) const { - return fTime >= dateTime.fTime && fDate >= dateTime.fDate; + if (fDate > dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime >= dateTime.fTime; + return false; } diff --git a/src/apps/webpositive/support/DateTime.h b/src/apps/webpositive/support/DateTime.h index fe92d86745..93f76399d6 100644 --- a/src/apps/webpositive/support/DateTime.h +++ b/src/apps/webpositive/support/DateTime.h @@ -33,6 +33,7 @@ enum diff_type { class BTime { public: BTime(); + BTime(const BTime& other); BTime(int32 hour, int32 minute, int32 second, int32 microsecond = 0); BTime(const BMessage* archive); @@ -52,11 +53,11 @@ public: bool SetTime(int32 hour, int32 minute, int32 second, int32 microsecond = 0); - void AddHours(int32 hours); - void AddMinutes(int32 minutes); - void AddSeconds(int32 seconds); - void AddMilliseconds(int32 milliseconds); - void AddMicroseconds(int32 microseconds); + 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; @@ -77,7 +78,7 @@ public: private: bigtime_t _Microseconds() const; - void _AddMicroseconds(bigtime_t microseconds); + BTime& _AddMicroseconds(bigtime_t microseconds); bool _SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, bigtime_t microsecond); @@ -89,6 +90,7 @@ private: class BDate { public: BDate(); + BDate(const BDate& other); BDate(int32 year, int32 month, int32 day); BDate(const BMessage* archive); ~BDate(); @@ -126,11 +128,17 @@ public: int32 DaysInYear() const; int32 DaysInMonth() const; - BString ShortDayName(int32 day) const; - BString ShortMonthName(int32 month) const; + BString ShortDayName() const; + static BString ShortDayName(int32 day); - BString LongDayName(int32 day) const; - BString LongMonthName(int32 month) const; + 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); @@ -171,10 +179,12 @@ public: static BDateTime CurrentDateTime(time_type type); void SetDateTime(const BDate &date, const BTime &time); - BDate Date() const; + BDate& Date(); + const BDate& Date() const; void SetDate(const BDate &date); - BTime Time() const; + BTime& Time(); + const BTime& Time() const; void SetTime(const BTime &time); int32 Time_t() const; From 2e8e305ebc16cfbf553f4b72f14255615ffb43be Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:39:46 +0000 Subject: [PATCH 111/293] * Fixed bug that would save the history for each item in the history when loading the history from disk... * Don't touch items when loading them from disk, messing up their visited time. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@323 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 56 ++++++++++++++---------- src/apps/webpositive/BrowsingHistory.h | 1 + 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index e5a7e8afe4..c93482e088 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -154,7 +154,7 @@ BrowsingHistory::BrowsingHistory() BMessage historyItemArchive; for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - addItem(BrowsingHistoryItem(&historyItemArchive)); + privateAddItem(BrowsingHistoryItem(&historyItemArchive), false); historyItemArchive.MakeEmpty(); } } @@ -177,28 +177,7 @@ bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) { BAutolock _(this); - int32 count = countItems(); - int32 insertionIndex = count; - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.ItemAtFast(i)); - if (item.url() == existingItem->url()) { - existingItem->invoked(); - return true; - } - if (item < *existingItem) - insertionIndex = i; - } - BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); - if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { - delete newItem; - return false; - } - - newItem->invoked(); - saveSettings(); - - return true; + return privateAddItem(item, false); } int32 BrowsingHistory::BrowsingHistory::countItems() const @@ -238,6 +217,37 @@ void BrowsingHistory::privateClear() m_historyItems.MakeEmpty(); } +bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool internal) +{ + int32 count = countItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.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 || !m_historyItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + if (!internal) { + newItem->invoked(); + saveSettings(); + } + + return true; +} + // #pragma mark - private void BrowsingHistory::saveSettings() diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 00e4f3a5e7..e25dee27ed 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -79,6 +79,7 @@ private: BrowsingHistory(); virtual ~BrowsingHistory(); void privateClear(); + bool privateAddItem(const BrowsingHistoryItem& item, bool invoke); void saveSettings(); bool openSettingsFile(BFile& file, uint32 mode); From e405ff6af725ad922878842ea679edbabaa42bd7 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:40:58 +0000 Subject: [PATCH 112/293] * Improved the Go menu by sorting items into sub-menus for each day, five days into the past, and the rest of them into "Earlier". * Moved the "Clear history" item to the top. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@324 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 83 ++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0a5d2f6940..a0e104ca7c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -683,6 +683,16 @@ BrowserWindow::QuitRequested() } +static void +addOrDeleteMenu(BMenu* menu, BMenu* toMenu) +{ + if (menu->CountItems() > 0) + toMenu->AddItem(menu); + else + delete menu; +} + + void BrowserWindow::MenusBeginning() { @@ -695,25 +705,78 @@ BrowserWindow::MenusBeginning() return; int32 count = history->countItems(); + BMenuItem* clearHistoryItem = new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY)); + clearHistoryItem->SetEnabled(count > 0); + fGoMenu->AddItem(clearHistoryItem); + if (count == 0) { + history->Unlock(); + return; + } + fGoMenu->AddSeparatorItem(); + + BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); + todayStart.SetTime(BTime(0, 0, 0)); + + BDateTime oneDayAgoStart = todayStart; + oneDayAgoStart.Date().AddDays(-1); + + BDateTime twoDaysAgoStart = oneDayAgoStart; + twoDaysAgoStart.Date().AddDays(-1); + + BDateTime threeDaysAgoStart = twoDaysAgoStart; + threeDaysAgoStart.Date().AddDays(-1); + + BDateTime fourDaysAgoStart = threeDaysAgoStart; + fourDaysAgoStart.Date().AddDays(-1); + + BDateTime fiveDaysAgoStart = fourDaysAgoStart; + fiveDaysAgoStart.Date().AddDays(-1); + + BMenu* todayMenu = new BMenu("Today"); + BMenu* yesterdayMenu = new BMenu("Yesterday"); + BMenu* twoDaysAgoMenu = new BMenu( + twoDaysAgoStart.Date().LongDayName().String()); + BMenu* threeDaysAgoMenu = new BMenu( + threeDaysAgoStart.Date().LongDayName().String()); + BMenu* fourDaysAgoMenu = new BMenu( + fourDaysAgoStart.Date().LongDayName().String()); + BMenu* fiveDaysAgoMenu = new BMenu( + fiveDaysAgoStart.Date().LongDayName().String()); + BMenu* earlierMenu = new BMenu("Earlier"); + for (int32 i = 0; i < count; i++) { BrowsingHistoryItem historyItem = history->historyItemAt(i); BMessage* message = new BMessage(GOTO_URL); message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... + BString truncatedUrl(historyItem.url()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - fGoMenu->AddItem(menuItem); + + if (historyItem.dateTime() < fiveDaysAgoStart) + earlierMenu->AddItem(menuItem); + else if (historyItem.dateTime() < fourDaysAgoStart) + fiveDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < threeDaysAgoStart) + fourDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < twoDaysAgoStart) + threeDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < oneDayAgoStart) + twoDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < todayStart) + yesterdayMenu->AddItem(menuItem); + else + todayMenu->AddItem(menuItem); } - - - if (fGoMenu->CountItems() > 3) { - fGoMenu->AddSeparatorItem(); - fGoMenu->AddItem(new BMenuItem("Clear history", - new BMessage(CLEAR_HISTORY))); - } - history->Unlock(); + + addOrDeleteMenu(todayMenu, fGoMenu); + addOrDeleteMenu(yesterdayMenu, fGoMenu); + addOrDeleteMenu(twoDaysAgoMenu, fGoMenu); + addOrDeleteMenu(fourDaysAgoMenu, fGoMenu); + addOrDeleteMenu(fiveDaysAgoMenu, fGoMenu); + addOrDeleteMenu(earlierMenu, fGoMenu); } From 7cbf0e1d7e1a9a9f0cc28151bb9ed7e0c09eff21 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:44:34 +0000 Subject: [PATCH 113/293] Fix the history restoration for real... duh! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@325 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index c93482e088..cadb86e5bb 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -154,7 +154,7 @@ BrowsingHistory::BrowsingHistory() BMessage historyItemArchive; for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - privateAddItem(BrowsingHistoryItem(&historyItemArchive), false); + privateAddItem(BrowsingHistoryItem(&historyItemArchive), true); historyItemArchive.MakeEmpty(); } } @@ -206,6 +206,8 @@ void BrowsingHistory::clear() saveSettings(); } +// #pragma mark - private + void BrowsingHistory::privateClear() { int32 count = countItems(); @@ -248,8 +250,6 @@ bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool inter return true; } -// #pragma mark - private - void BrowsingHistory::saveSettings() { BFile settingsFile; From f1dcf19d1d35e7e8695ca9beaa52e2dcc9fcb510 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 11:35:23 +0000 Subject: [PATCH 114/293] Sort items in the Go menu into submenus per base URL. This further reduces the clutter there. I'm quite happy now, but one issue could be that the Go menu is not stable: Any URL will always appear only once, somewhere in the hierarchy, depending on when you last visited it. The BrowsingHistory could be changed, though, feedback welcome. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@330 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 59 +++++++++++++++++++++----- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a0e104ca7c..33469bd5b0 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -131,6 +131,17 @@ private: }; +static 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; +} + + class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { virtual void FetchChoicesFor(const BString& pattern) { @@ -161,10 +172,7 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { priority--; } else priority = INT_MAX; - int32 baseURLStart = choiceText.FindFirst("://") + 3; - int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); - lastBaseURL.SetTo(choiceText.String() + baseURLStart, - baseURLEnd - baseURLStart); + lastBaseURL = baseURL(choiceText); fChoices.AddItem(new URLChoice(choiceText, choiceText, matchPos, pattern.Length(), priority)); } @@ -683,6 +691,35 @@ BrowserWindow::QuitRequested() } +static void +addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) +{ + BString baseURLLabel = baseURL(BString(newItem->Label())); + for (int32 i = menu->CountItems() - 1; i >= 0; i--) { + BMenuItem* item = menu->ItemAt(i); + BString label = item->Label(); + if (label.FindFirst(baseURLLabel) >= 0) { + if (item->Submenu()) { + // Submenu was already added in previous iteration. + item->Submenu()->AddItem(newItem); + return; + } else { + menu->RemoveItem(item); + BMenu* subMenu = new BMenu(baseURLLabel.String()); + subMenu->AddItem(item); + subMenu->AddItem(newItem); + // Add common submenu for this base URL, clickable. + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", baseURLLabel.String()); + menu->AddItem(new BMenuItem(subMenu, message)); + return; + } + } + } + menu->AddItem(newItem); +} + + static void addOrDeleteMenu(BMenu* menu, BMenu* toMenu) { @@ -755,19 +792,19 @@ BrowserWindow::MenusBeginning() menuItem = new BMenuItem(truncatedUrl, message); if (historyItem.dateTime() < fiveDaysAgoStart) - earlierMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(earlierMenu, menuItem); else if (historyItem.dateTime() < fourDaysAgoStart) - fiveDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); else if (historyItem.dateTime() < threeDaysAgoStart) - fourDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); else if (historyItem.dateTime() < twoDaysAgoStart) - threeDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); else if (historyItem.dateTime() < oneDayAgoStart) - twoDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); else if (historyItem.dateTime() < todayStart) - yesterdayMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(yesterdayMenu, menuItem); else - todayMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(todayMenu, menuItem); } history->Unlock(); From 0fc94bdcbc50b4122603ac653a61f8349bb5e0d3 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 11:36:36 +0000 Subject: [PATCH 115/293] At the common submenu at the location where the item was removed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@331 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 33469bd5b0..55cac2f605 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -711,7 +711,7 @@ addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) // Add common submenu for this base URL, clickable. BMessage* message = new BMessage(GOTO_URL); message->AddString("url", baseURLLabel.String()); - menu->AddItem(new BMenuItem(subMenu, message)); + menu->AddItem(new BMenuItem(subMenu, message), i); return; } } From cb8b9e4ffd504ced209fb21ee0c4c577f3ae3554 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 13:03:26 +0000 Subject: [PATCH 116/293] Some notifications are now channeled through BWebPage, the loading progress and status. This allows the browser to set those properties to the current page when switching pages. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@333 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 55cac2f605..ad6a19b6e1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -832,7 +832,7 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) if (select) { fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); - NavigationCapabilitiesChanged(false, false, false, webView); + webView->WebPage()->ResendNotifications(); if (fURLTextControl) { fURLTextControl->SetText(url.String()); fURLTextControl->MakeFocus(true); @@ -880,7 +880,7 @@ BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); } @@ -896,7 +896,7 @@ BrowserWindow::LoadCommitted(const BString& url, BWebView* view) BString status("Loading: "); status << url; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); } @@ -909,6 +909,8 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) if (fLoadingProgressBar) { if (progress < 100 && fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Show(); + else if (progress == 100 && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); fLoadingProgressBar->SetTo(progress); } } @@ -922,7 +924,7 @@ BrowserWindow::LoadFailed(const BString& url, BWebView* view) BString status(url); status << " failed."; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } @@ -936,7 +938,7 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) BString status(url); status << " finished."; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); From e91fdd924a9e7b92f9254ec3082d2f6e5485875e Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Mar 2010 17:15:42 +0000 Subject: [PATCH 117/293] * Converted BrowsingHistory.h/cpp to Haiku coding style. * Probably fixed a race condition on program launch. If you started typing into the URL field really fast, the static instance in BrowsingHistory::DefaultInstance() could be created by two threads, which may be responsible for the "recursive init" exception that GCC throws in this situation. It's not easy to trigger, maybe this was it. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@335 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 3 +- src/apps/webpositive/BrowserWindow.cpp | 38 +-- src/apps/webpositive/BrowsingHistory.cpp | 368 ++++++++++++++--------- src/apps/webpositive/BrowsingHistory.h | 88 +++--- 4 files changed, 292 insertions(+), 205 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index e4b4c10d15..7bbb63c633 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -169,7 +169,8 @@ BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { case PRELOAD_BROWSING_HISTORY: - BrowsingHistory::defaultInstance(); + // Accessing the default instance will load the history from disk. + BrowsingHistory::DefaultInstance(); break; case B_SILENT_RELAUNCH: _CreateNewPage(""); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ad6a19b6e1..0c60ca1f91 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -153,17 +153,17 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { fChoices.MakeEmpty(); // Search through BrowsingHistory for any matches. - BrowsingHistory* history = BrowsingHistory::defaultInstance(); + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); if (!history->Lock()) return; BString lastBaseURL; int32 priority = INT_MAX; - count = history->countItems(); + count = history->CountItems(); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem item = history->historyItemAt(i); - const BString& choiceText = item.url(); + BrowsingHistoryItem item = history->HistoryItemAt(i); + const BString& choiceText = item.URL(); int32 matchPos = choiceText.IFindFirst(pattern); if (matchPos < 0) continue; @@ -499,13 +499,13 @@ BrowserWindow::MessageReceived(BMessage* message) break; case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (history->CountItems() == 0) break; BAlert* alert = new BAlert("Confirmation", "Do you really want to " "clear the browsing history?", "Clear", "Cancel"); if (alert->Go() == 0) - history->clear(); + history->Clear(); break; } @@ -737,11 +737,11 @@ BrowserWindow::MenusBeginning() while ((menuItem = fGoMenu->RemoveItem(0L))) delete menuItem; - BrowsingHistory* history = BrowsingHistory::defaultInstance(); + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); if (!history->Lock()) return; - int32 count = history->countItems(); + int32 count = history->CountItems(); BMenuItem* clearHistoryItem = new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY)); clearHistoryItem->SetEnabled(count > 0); @@ -783,25 +783,25 @@ BrowserWindow::MenusBeginning() BMenu* earlierMenu = new BMenu("Earlier"); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); + BrowsingHistoryItem historyItem = history->HistoryItemAt(i); BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); + message->AddString("url", historyItem.URL().String()); - BString truncatedUrl(historyItem.url()); + BString truncatedUrl(historyItem.URL()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - if (historyItem.dateTime() < fiveDaysAgoStart) + if (historyItem.DateTime() < fiveDaysAgoStart) addItemToMenuOrSubmenu(earlierMenu, menuItem); - else if (historyItem.dateTime() < fourDaysAgoStart) + else if (historyItem.DateTime() < fourDaysAgoStart) addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < threeDaysAgoStart) + else if (historyItem.DateTime() < threeDaysAgoStart) addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < twoDaysAgoStart) + else if (historyItem.DateTime() < twoDaysAgoStart) addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < oneDayAgoStart) + else if (historyItem.DateTime() < oneDayAgoStart) addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < todayStart) + else if (historyItem.DateTime() < todayStart) addItemToMenuOrSubmenu(yesterdayMenu, menuItem); else addItemToMenuOrSubmenu(todayMenu, menuItem); @@ -1048,7 +1048,7 @@ BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, void BrowserWindow::UpdateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::DefaultInstance()->AddItem(BrowsingHistoryItem(url)); } diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index cadb86e5bb..f89d4bf77f 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -25,251 +25,321 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowsingHistory.h" -#include "BrowserApp.h" +#include +#include + #include #include #include #include #include #include -#include -#include + +#include "BrowserApp.h" BrowsingHistoryItem::BrowsingHistoryItem(const BString& url) - : m_url(url) - , m_dateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)) - , m_invokationCount(0) + : + 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; + return; BMessage dateTimeArchive; if (archive->FindMessage("date time", &dateTimeArchive) == B_OK) - m_dateTime = BDateTime(&dateTimeArchive); - archive->FindString("url", &m_url); - archive->FindUInt32("invokations", &m_invokationCount); + fDateTime = BDateTime(&dateTimeArchive); + archive->FindString("url", &fURL); + archive->FindUInt32("invokations", &fInvokationCount); } + BrowsingHistoryItem::~BrowsingHistoryItem() { } -status_t BrowsingHistoryItem::archive(BMessage* archive) const + +status_t +BrowsingHistoryItem::Archive(BMessage* archive) const { if (!archive) - return B_BAD_VALUE; + return B_BAD_VALUE; BMessage dateTimeArchive; - status_t status = m_dateTime.Archive(&dateTimeArchive); + status_t status = fDateTime.Archive(&dateTimeArchive); if (status == B_OK) - status = archive->AddMessage("date time", &dateTimeArchive); + status = archive->AddMessage("date time", &dateTimeArchive); if (status == B_OK) - status = archive->AddString("url", m_url.String()); + status = archive->AddString("url", fURL.String()); if (status == B_OK) - status = archive->AddUInt32("invokations", m_invokationCount); - return status; + status = archive->AddUInt32("invokations", fInvokationCount); + return status; } -BrowsingHistoryItem& BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) -{ - if (this == &other) - return *this; - m_url = other.m_url; - m_dateTime = other.m_dateTime; - m_invokationCount = other.m_invokationCount; - - return *this; -} - -bool BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const +BrowsingHistoryItem& +BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) { if (this == &other) - return true; + return *this; - return m_url == other.m_url && m_dateTime == other.m_dateTime - && m_invokationCount == other.m_invokationCount; + fURL = other.fURL; + fDateTime = other.fDateTime; + fInvokationCount = other.fInvokationCount; + + return *this; } -bool BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const + +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 + +bool +BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const { if (this == &other) - return false; + return false; - return m_dateTime < other.m_dateTime || m_url < other.m_url; + return fDateTime < other.fDateTime || fURL < other.fURL; } -bool BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const { return (*this == other) || (*this < other); } -bool BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const { if (this == &other) - return false; + return false; - return m_dateTime > other.m_dateTime || m_url > other.m_url; + return fDateTime > other.fDateTime || fURL > other.fURL; } -bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const { return (*this == other) || (*this > other); } -void BrowsingHistoryItem::invoked() + +void +BrowsingHistoryItem::Invoked() { // Eventually, we may overflow... - uint32 count = m_invokationCount + 1; - if (count > m_invokationCount) - m_invokationCount = count; - m_dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); + 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") + : + BLocker("browsing history"), + fHistoryItems(64), + 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(this)); + + return fHistoryItems.CountItems(); +} + + +BrowsingHistoryItem +BrowsingHistory::HistoryItemAt(int32 index) const +{ + BAutolock _(const_cast(this)); + + BrowsingHistoryItem* existingItem = reinterpret_cast( + fHistoryItems.ItemAt(index)); + if (!existingItem) + return BrowsingHistoryItem(BString()); + + return BrowsingHistoryItem(*existingItem); +} + + +void +BrowsingHistory::Clear() +{ + BAutolock _(this); + _Clear(); + _SaveSettings(); +} + + +// #pragma mark - private + + +void +BrowsingHistory::_Clear() +{ + int32 count = CountItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* item = reinterpret_cast( + 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( + 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)) { + if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); BMessage historyItemArchive; - for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - privateAddItem(BrowsingHistoryItem(&historyItemArchive), true); + for (int32 i = 0; settingsArchive.FindMessage("history item", i, + &historyItemArchive) == B_OK; i++) { + _AddItem(BrowsingHistoryItem(&historyItemArchive), true); historyItemArchive.MakeEmpty(); } } } -BrowsingHistory::~BrowsingHistory() -{ - saveSettings(); - privateClear(); -} -/*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() -{ - static BrowsingHistory defaultInstance; - - return &defaultInstance; -} - -bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) -{ - BAutolock _(this); - - return privateAddItem(item, false); -} - -int32 BrowsingHistory::BrowsingHistory::countItems() const -{ - BAutolock _(const_cast(this)); - - return m_historyItems.CountItems(); -} - -BrowsingHistoryItem BrowsingHistory::historyItemAt(int32 index) const -{ - BAutolock _(const_cast(this)); - - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.ItemAt(index)); - if (!existingItem) - return BrowsingHistoryItem(BString()); - - return BrowsingHistoryItem(*existingItem); -} - -void BrowsingHistory::clear() -{ - BAutolock _(this); - privateClear(); - saveSettings(); -} - -// #pragma mark - private - -void BrowsingHistory::privateClear() -{ - int32 count = countItems(); - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* item = reinterpret_cast( - m_historyItems.ItemAtFast(i)); - delete item; - } - m_historyItems.MakeEmpty(); -} - -bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool internal) -{ - int32 count = countItems(); - int32 insertionIndex = count; - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.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 || !m_historyItems.AddItem(newItem, insertionIndex)) { - delete newItem; - return false; - } - - if (!internal) { - newItem->invoked(); - saveSettings(); - } - - return true; -} - -void BrowsingHistory::saveSettings() +void +BrowsingHistory::_SaveSettings() { BFile settingsFile; - if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + if (_OpenSettingsFile(settingsFile, + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; BMessage historyItemArchive; - int32 count = countItems(); + 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; + 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) + +bool +BrowsingHistory::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index e25dee27ed..43ca33ac5c 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -24,9 +24,8 @@ * (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 BrowsingHistory_h -#define BrowsingHistory_h +#ifndef BROWSING_HISTORY_H +#define BROWSING_HISTORY_H #include "DateTime.h" #include @@ -35,58 +34,75 @@ class BFile; class BString; + class BrowsingHistoryItem { public: - BrowsingHistoryItem(const BString& url); - BrowsingHistoryItem(const BrowsingHistoryItem& other); - BrowsingHistoryItem(const BMessage* archive); - ~BrowsingHistoryItem(); + BrowsingHistoryItem(const BString& url); + BrowsingHistoryItem( + const BrowsingHistoryItem& other); + BrowsingHistoryItem(const BMessage* archive); + ~BrowsingHistoryItem(); - status_t archive(BMessage* archive) const; + status_t Archive(BMessage* archive) const; - BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other); + 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; + 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 m_url; } - const BDateTime& dateTime() const { return m_dateTime; } - uint32 invokationCount() const { return m_invokationCount; } - void invoked(); + const BString& URL() const { return fURL; } + const BDateTime& DateTime() const { return fDateTime; } + uint32 InvokationCount() const { + return fInvokationCount; } + void Invoked(); private: - BString m_url; - BDateTime m_dateTime; - uint32 m_invokationCount; + BString fURL; + BDateTime fDateTime; + uint32 fInvokationCount; }; + class BrowsingHistory : public BLocker { public: - static BrowsingHistory* defaultInstance(); + static BrowsingHistory* DefaultInstance(); - bool addItem(const BrowsingHistoryItem& item); + 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(); + // Should Lock() the object when using these in some loop or so: + int32 CountItems() const; + BrowsingHistoryItem HistoryItemAt(int32 index) const; + void Clear(); private: - BrowsingHistory(); - virtual ~BrowsingHistory(); - void privateClear(); - bool privateAddItem(const BrowsingHistoryItem& item, bool invoke); + BrowsingHistory(); + virtual ~BrowsingHistory(); - void saveSettings(); - bool openSettingsFile(BFile& file, uint32 mode); + void _Clear(); + bool _AddItem(const BrowsingHistoryItem& item, + bool invoke); + + void _LoadSettings(); + void _SaveSettings(); + bool _OpenSettingsFile(BFile& file, uint32 mode); private: - BList m_historyItems; + BList fHistoryItems; + + static BrowsingHistory sDefaultInstance; + bool fSettingsLoaded; }; -#endif // BrowsingHistory_h + +#endif // BROWSING_HISTORY_H From aa5ba348ea3f8d64cb7e0ac47904127f6e09b3f4 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Mar 2010 19:05:47 +0000 Subject: [PATCH 118/293] * Added General page in Settings window with option to specify the maximum age (in days) of items in the browsing history. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@336 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 31 +++- src/apps/webpositive/BrowsingHistory.h | 6 +- src/apps/webpositive/SettingsWindow.cpp | 190 +++++++++++++++++------ src/apps/webpositive/SettingsWindow.h | 13 ++ 4 files changed, 188 insertions(+), 52 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index f89d4bf77f..42a0442d0f 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -177,6 +177,7 @@ BrowsingHistory::BrowsingHistory() : BLocker("browsing history"), fHistoryItems(64), + fMaxHistoryItemAge(7), fSettingsLoaded(false) { } @@ -241,6 +242,24 @@ BrowsingHistory::Clear() } +void +BrowsingHistory::SetMaxHistoryItemAge(int32 days) +{ + BAutolock _(this); + if (fMaxHistoryItemAge != days) { + fMaxHistoryItemAge = days; + _SaveSettings(); + } +} + + +int32 +BrowsingHistory::MaxHistoryItemAge() const +{ + return fMaxHistoryItemAge; +} + + // #pragma mark - private @@ -303,11 +322,20 @@ BrowsingHistory::_LoadSettings() 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++) { - _AddItem(BrowsingHistoryItem(&historyItemArchive), true); + BrowsingHistoryItem item(&historyItemArchive); + if (oldestAllowedDateTime < item.DateTime()) + _AddItem(item, true); historyItemArchive.MakeEmpty(); } } @@ -321,6 +349,7 @@ BrowsingHistory::_SaveSettings() 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++) { diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 43ca33ac5c..bf8f7f15b8 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -84,6 +84,9 @@ public: BrowsingHistoryItem HistoryItemAt(int32 index) const; void Clear(); + void SetMaxHistoryItemAge(int32 days); + int32 MaxHistoryItemAge() const; + private: BrowsingHistory(); virtual ~BrowsingHistory(); @@ -98,8 +101,9 @@ private: private: BList fHistoryItems; + int32 fMaxHistoryItemAge; - static BrowsingHistory sDefaultInstance; + static BrowsingHistory sDefaultInstance; bool fSettingsLoaded; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 906a029dfb..e240147f2d 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -38,10 +38,15 @@ #include #include #include +#include +#include #include + #include +#include #include "BrowserApp.h" +#include "BrowsingHistory.h" #include "FontSelectionView.h" #include "SettingsMessage.h" #include "WebSettings.h" @@ -56,6 +61,9 @@ enum { MSG_REVERT = 'rvrt', MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', + MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', + MSG_GO_MENU_DAYS_CHANGED = 'digm', }; static const int32 kDefaultFontSize = 14; @@ -69,68 +77,28 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) { SetLayout(new BGroupLayout(B_VERTICAL)); - fStandardFontView = new FontSelectionView("standard", "Standard font:", - true, be_plain_font); - BFont defaultSerifFont = _FindDefaultSerifFont(); - fSerifFontView = new FontSelectionView("serif", "Serif font:", true, - &defaultSerifFont); - fSansSerifFontView = new FontSelectionView("sans serif", "Sans serif font:", - true, be_plain_font); - fFixedFontView = new FontSelectionView("fixed", "Fixed font:", true, - be_fixed_font); - - fStandardSizesMenu = new BMenuField("standard font size", - TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); - - fFixedSizesMenu = new BMenuField("fixed font size", - TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); - - fApplyButton = new BButton("Apply", new BMessage(MSG_APPLY)); - fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); - fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); + fApplyButton = new BButton(TR("Apply"), new BMessage(MSG_APPLY)); + fCancelButton = new BButton(TR("Cancel"), new BMessage(MSG_CANCEL)); + fRevertButton = new BButton(TR("Revert"), new BMessage(MSG_REVERT)); float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(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) + BTabView* tabView = new BTabView("settings pages", B_WIDTH_FROM_LABEL); - .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) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + AddChild(BGroupLayoutBuilder(B_VERTICAL, spacing) + .Add(tabView) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .Add(fRevertButton) .AddGlue() .Add(fCancelButton) .Add(fApplyButton) - .SetInsets(spacing, spacing, spacing, spacing) ) + .SetInsets(spacing, spacing, spacing, spacing) ); + tabView->AddTab(_CreateGeneralPage(spacing)); + tabView->AddTab(_CreateFontsPage(spacing)); + AddHandler(fStandardFontView); fStandardFontView->AttachedToLooper(); @@ -229,6 +197,118 @@ SettingsWindow::Show() // #pragma mark - private +BView* +SettingsWindow::_CreateGeneralPage(float spacing) +{ + fDownloadFolderControl = new BTextControl("download folder", + TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); +fDownloadFolderControl->SetEnabled(false); + + fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + NULL); + fNewPageBehaviorCloneCurrentItem->SetEnabled(false); + fNewPageBehaviorOpenHomeItem = new BMenuItem(TR("Open home page"), NULL); + fNewPageBehaviorOpenHomeItem->SetEnabled(false); + fNewPageBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewPageBehaviorOpenSearchItem->SetEnabled(false); + fNewPageBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); + fNewPageBehaviorOpenBlankItem->SetMarked(true); + + BPopUpMenu* newPageBehaviorMenu = new BPopUpMenu("New pages"); + newPageBehaviorMenu->AddItem(fNewPageBehaviorCloneCurrentItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenHomeItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenSearchItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenBlankItem); + fNewPageBehaviorMenu = new BMenuField("new page behavior", + TR("New pages:"), newPageBehaviorMenu, + new BMessage(MSG_NEW_PAGE_BEHAVIOR_CHANGED)); +fNewPageBehaviorMenu->SetEnabled(false); + + fDaysInGoMenuControl = new BTextControl("days in go menu", + TR("Number of days to keep links in Go menu:"), "", + new BMessage(MSG_GO_MENU_DAYS_CHANGED)); + BString maxHistoryAge; + maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); + fDaysInGoMenuControl->SetText(maxHistoryAge.String()); + for (uchar i = 0; i < '0'; i++) + fDaysInGoMenuControl->TextView()->DisallowChar(i); + for (uchar i = '9' + 1; i <= 128; i++) + fDaysInGoMenuControl->TextView()->DisallowChar(i); + + BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) + .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) + + .Add(fNewPageBehaviorMenu->CreateLabelLayoutItem(), 0, 2) + .Add(fNewPageBehaviorMenu->CreateMenuBarLayoutItem(), 1, 2) + + .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) + .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) + + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 4, 2) + + .SetInsets(spacing, spacing, spacing, spacing) + ; + view->SetName("General"); + return view; +} + + +BView* +SettingsWindow::_CreateFontsPage(float spacing) +{ + fStandardFontView = new FontSelectionView("standard", TR("Standard font:"), + true, be_plain_font); + BFont defaultSerifFont = _FindDefaultSerifFont(); + fSerifFontView = new FontSelectionView("serif", TR("Serif font:"), true, + &defaultSerifFont); + fSansSerifFontView = new FontSelectionView("sans serif", + TR("Sans serif font:"), true, be_plain_font); + fFixedFontView = new FontSelectionView("fixed", TR("Fixed font:"), true, + be_fixed_font); + + fStandardSizesMenu = new BMenuField("standard font size", + TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + + fFixedSizesMenu = new BMenuField("fixed font size", + TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + _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->SetName("Fonts"); + return view; +} + + void SettingsWindow::_ApplySettings() { @@ -255,6 +335,16 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); + + int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + if (maxHistoryAge <= 0) + maxHistoryAge = 1; + if (maxHistoryAge >= 35) + maxHistoryAge = 35; + BString text; + text << maxHistoryAge; + fDaysInGoMenuControl->SetText(text.String()); + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); } diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 9a6b7d9373..124b85f7e6 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -32,6 +32,8 @@ class BButton; class BMenu; class BMenuField; +class BMenuItem; +class BTextControl; class FontSelectionView; class SettingsMessage; @@ -48,6 +50,9 @@ public: virtual void Show(); private: + BView* _CreateGeneralPage(float spacing); + BView* _CreateFontsPage(float spacing); + void _ApplySettings(); void _RevertSettings(); @@ -61,6 +66,14 @@ private: private: SettingsMessage* fSettings; + BTextControl* fDownloadFolderControl; + BMenuField* fNewPageBehaviorMenu; + BMenuItem* fNewPageBehaviorCloneCurrentItem; + BMenuItem* fNewPageBehaviorOpenHomeItem; + BMenuItem* fNewPageBehaviorOpenSearchItem; + BMenuItem* fNewPageBehaviorOpenBlankItem; + BTextControl* fDaysInGoMenuControl; + FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; FontSelectionView* fSansSerifFontView; From 9ccfda9c50ab958a4545588d888850694ec86ee5 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 16:59:50 +0000 Subject: [PATCH 119/293] Converted to Haiku coding style. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@337 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 792 +++++++++++++----------- src/apps/webpositive/DownloadWindow.h | 31 +- 2 files changed, 435 insertions(+), 388 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 60d9701e9b..f852cb6f2e 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -25,12 +25,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "DownloadWindow.h" -#include "BrowserApp.h" -#include "WebDownload.h" -#include "WebPage.h" +#include + #include #include #include @@ -48,296 +46,310 @@ #include #include #include -#include + +#include "BrowserApp.h" +#include "WebDownload.h" +#include "WebPage.h" + enum { - REMOVE_FINISHED_DOWNLOADS = 'rmfd', - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', - SAVE_SETTINGS = 'svst' + REMOVE_FINISHED_DOWNLOADS = 'rmfd', + OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', + REMOVE_DOWNLOAD = 'rmdn', + SAVE_SETTINGS = 'svst' }; + class IconView : public BView { public: - IconView(const BEntry& entry) - : BView("Download icon", B_WILL_DRAW) - , m_iconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) - { - BNode node(&entry); - BNodeInfo info(&node); - info.GetTrackerIcon(&m_iconBitmap, B_LARGE_ICON); - SetDrawingMode(B_OP_OVER); - } + IconView(const BEntry& entry) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); + SetDrawingMode(B_OP_OVER); + } - IconView(BMessage* archive) - : BView("Download icon", B_WILL_DRAW) - , m_iconBitmap(archive) - { - SetDrawingMode(B_OP_OVER); - } + IconView(BMessage* archive) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(archive) + { + SetDrawingMode(B_OP_OVER); + } - status_t saveSettings(BMessage* archive) - { - return m_iconBitmap.Archive(archive); - } + status_t SaveSettings(BMessage* archive) + { + return fIconBitmap.Archive(archive); + } - virtual void AttachedToWindow() - { - SetViewColor(Parent()->ViewColor()); - } + virtual void AttachedToWindow() + { + SetViewColor(Parent()->ViewColor()); + } - virtual void Draw(BRect updateRect) - { - DrawBitmapAsync(&m_iconBitmap); - } + virtual void Draw(BRect updateRect) + { + DrawBitmapAsync(&fIconBitmap); + } - virtual BSize MinSize() - { - return BSize(m_iconBitmap.Bounds().Width(), m_iconBitmap.Bounds().Height()); - } + virtual BSize MinSize() + { + return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height()); + } - virtual BSize PreferredSize() - { - return MinSize(); - } + virtual BSize PreferredSize() + { + return MinSize(); + } - virtual BSize MaxSize() - { - return MinSize(); - } + virtual BSize MaxSize() + { + return MinSize(); + } private: - BBitmap m_iconBitmap; + BBitmap fIconBitmap; }; + 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); - } + 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); + } }; + class DownloadProgressView : public BGridView { public: - DownloadProgressView(BWebDownload* download) - : BGridView(8, 3) - , m_download(download) - , m_url(download->URL()) - , m_path(download->Path()) - , m_expectedSize(download->ExpectedSize()) - { - } + DownloadProgressView(BWebDownload* download) + : + BGridView(8, 3), + fDownload(download), + fURL(download->URL()), + fPath(download->Path()), + fExpectedSize(download->ExpectedSize()) + { + } - DownloadProgressView(const BMessage* archive) - : BGridView(8, 3) - , m_download(NULL) - , m_url() - , m_path() - , m_expectedSize(0) - { - const char* string; - if (archive->FindString("path", &string) == B_OK) - m_path.SetTo(string); - if (archive->FindString("url", &string) == B_OK) - m_url = string; - } + DownloadProgressView(const BMessage* archive) + : + BGridView(8, 3), + fDownload(NULL), + fURL(), + fPath(), + fExpectedSize(0) + { + const char* string; + if (archive->FindString("path", &string) == B_OK) + fPath.SetTo(string); + if (archive->FindString("url", &string) == B_OK) + fURL = string; + } - bool init(BMessage* archive = NULL) - { - BEntry entry(m_path.Path()); - if (!entry.Exists() && !archive) - return false; + bool Init(BMessage* archive = NULL) + { + BEntry entry(fPath.Path()); + if (!entry.Exists() && !archive) + return false; - SetViewColor(245, 245, 245); - SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); - BGridLayout* layout = GridLayout(); - m_statusBar = new BStatusBar("download progress", m_path.Leaf()); - m_statusBar->SetMaxValue(100); - if (archive) { - float value; - if (archive->FindFloat("value", &value) == B_OK) - m_statusBar->SetTo(value); - } - m_statusBar->SetBarHeight(12); + BGridLayout* layout = GridLayout(); + fStatusBar = new BStatusBar("download progress", fPath.Leaf()); + fStatusBar->SetMaxValue(100); + if (archive) { + float value; + if (archive->FindFloat("value", &value) == B_OK) + fStatusBar->SetTo(value); + } + fStatusBar->SetBarHeight(12); - if (entry.Exists()) - m_iconView = new IconView(entry); - else - m_iconView = new IconView(archive); + if (entry.Exists()) + fIconView = new IconView(entry); + else + fIconView = new IconView(archive); - if (!m_download && m_statusBar->CurrentValue() < 100) - m_button1 = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); - else { - m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); - m_button1->SetEnabled(m_download == NULL); - } - if (m_download) - m_button2 = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); - else { - m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(m_download == NULL); - } + if (!fDownload && fStatusBar->CurrentValue() < 100) + 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); + } layout->SetInsets(8, 5, 5, 6); - layout->AddView(m_iconView, 0, 0, 1, 2); - layout->AddView(m_statusBar, 1, 0, 1, 2); - layout->AddView(m_button1, 2, 0); - layout->AddView(m_button2, 2, 1); + layout->AddView(fIconView, 0, 0, 1, 2); + layout->AddView(fStatusBar, 1, 0, 1, 2); + layout->AddView(fTopButton, 2, 0); + layout->AddView(fBottomButton, 2, 1); - return true; - } + return true; + } - status_t saveSettings(BMessage* archive) - { - if (!archive) - return B_BAD_VALUE; - status_t ret = archive->AddString("path", m_path.Path()); - if (ret == B_OK) - ret = archive->AddString("url", m_url.String()); - if (ret == B_OK) - ret = archive->AddFloat("value", m_statusBar->CurrentValue()); - if (ret == B_OK) - ret = m_iconView->saveSettings(archive); - return ret; - } + status_t 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; + } - virtual void AttachedToWindow() - { - if (m_download) - m_download->SetProgressListener(BMessenger(this)); - m_button1->SetTarget(this); - m_button2->SetTarget(this); - } + virtual void AttachedToWindow() + { + if (fDownload) + fDownload->SetProgressListener(BMessenger(this)); + fTopButton->SetTarget(this); + fBottomButton->SetTarget(this); + } - virtual void AllAttached() - { - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(245, 245, 245); - SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); - } + virtual void AllAttached() + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(245, 245, 245); + SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); + } - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - bounds.bottom--; - FillRect(bounds, B_SOLID_LOW); - bounds.bottom++; - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - } + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + bounds.bottom--; + FillRect(bounds, B_SOLID_LOW); + bounds.bottom++; + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + } - virtual void MessageReceived(BMessage* message) - { - switch (message->what) { - case B_DOWNLOAD_PROGRESS: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - m_statusBar->SetTo(progress); - break; - } - case OPEN_DOWNLOAD: { - // TODO: In case of executable files, ask the user first! - entry_ref ref; - status_t status = get_ref_for_path(m_path.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(m_url); - break; + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case B_DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + fStatusBar->SetTo(progress); + 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_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; + default: + BGridView::MessageReceived(message); + } + } - case CANCEL_DOWNLOAD: - m_download->Cancel(); - downloadCanceled(); - break; + BWebDownload* Download() const + { + return fDownload; + } - case REMOVE_DOWNLOAD: { - Window()->PostMessage(SAVE_SETTINGS); - RemoveSelf(); - delete this; - // TOAST! - return; - } - 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; - default: - BGridView::MessageReceived(message); - } - } + const BString& URL() const + { + return fURL; + } - BWebDownload* download() const - { - return m_download; - } + void DownloadFinished() + { + fDownload = NULL; + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); + } - const BString& url() const - { - return m_url; - } - - void downloadFinished() - { - m_download = NULL; - m_button1->SetEnabled(true); - m_button2->SetLabel("Remove"); - m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(true); - } - - void downloadCanceled() - { - m_download = NULL; - m_button1->SetLabel("Restart"); - m_button1->SetMessage(new BMessage(RESTART_DOWNLOAD)); - m_button1->SetEnabled(true); - m_button2->SetLabel("Remove"); - m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(true); - } + void 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); + } private: - IconView* m_iconView; - BStatusBar* m_statusBar; - SmallButton* m_button1; - SmallButton* m_button2; - BWebDownload* m_download; - BString m_url; - BPath m_path; - off_t m_expectedSize; + IconView* fIconView; + BStatusBar* fStatusBar; + SmallButton* fTopButton; + SmallButton* fBottomButton; + BWebDownload* fDownload; + BString fURL; + BPath fPath; + off_t fExpectedSize; }; + class DownloadsContainerView : public BGroupView { public: DownloadsContainerView() - : BGroupView(B_VERTICAL) + : + BGroupView(B_VERTICAL) { - SetViewColor(245, 245, 245); - AddChild(BSpaceLayoutItem::CreateGlue()); + SetViewColor(245, 245, 245); + AddChild(BSpaceLayoutItem::CreateGlue()); } - virtual BSize MinSize() - { - BSize minSize = BGroupView::MinSize(); - return BSize(minSize.width, 80); - } + virtual BSize MinSize() + { + BSize minSize = BGroupView::MinSize(); + return BSize(minSize.width, 80); + } protected: virtual void DoLayout() @@ -349,211 +361,245 @@ protected: float max = minSize.height - height; scrollBar->SetRange(0, max); if (minSize.height > 0) - scrollBar->SetProportion(height / minSize.height); + scrollBar->SetProportion(height / minSize.height); else - scrollBar->SetProportion(1); + scrollBar->SetProportion(1); } } }; + class DownloadContainerScrollView : public BScrollView { public: - DownloadContainerScrollView(BView* target) - : BScrollView("Downloads scroll view", target, 0, false, true, B_NO_BORDER) - { - } + 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); - } + 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); + } }; + DownloadWindow::DownloadWindow(BRect frame, bool visible) - : BWindow(frame, "Downloads", - B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) + : BWindow(frame, "Downloads", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); - m_downloadViewsLayout = downloadsGroupView->GroupLayout(); + fDownloadViewsLayout = downloadsGroupView->GroupLayout(); - BMenuBar* menuBar = new BMenuBar("Menu bar"); - BMenu* menu = new BMenu("Window"); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); - menuBar->AddItem(menu); + BMenuBar* menuBar = new BMenuBar("Menu bar"); + BMenu* menu = new BMenu("Window"); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); + menuBar->AddItem(menu); - BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); + BScrollView* scrollView = new DownloadContainerScrollView( + downloadsGroupView); - m_removeFinishedButton = new BButton("Remove finished", - new BMessage(REMOVE_FINISHED_DOWNLOADS)); - m_removeFinishedButton->SetEnabled(false); + fRemoveFinishedButton = new BButton("Remove finished", + new BMessage(REMOVE_FINISHED_DOWNLOADS)); + fRemoveFinishedButton->SetEnabled(false); - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(menuBar) - .Add(scrollView) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL) - .AddGlue() - .Add(m_removeFinishedButton) - .SetInsets(5, 5, 5, 5) - ) - ); + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(menuBar) + .Add(scrollView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .AddGlue() + .Add(fRemoveFinishedButton) + .SetInsets(5, 5, 5, 5) + ) + ); - loadSettings(); - // Small trick to get the correct enabled status of the Remove finished button - downloadFinished(NULL); + _LoadSettings(); + // Small trick to get the correct enabled status of the Remove finished button + _DownloadFinished(NULL); if (!visible) - Hide(); + Hide(); Show(); } + DownloadWindow::~DownloadWindow() { // Only necessary to save the current progress of unfinished downloads: - saveSettings(); + _SaveSettings(); } -void DownloadWindow::MessageReceived(BMessage* message) + +void +DownloadWindow::MessageReceived(BMessage* message) { - switch (message->what) { - case B_DOWNLOAD_ADDED: { - BWebDownload* download; - if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) - downloadStarted(download); - break; - } - case B_DOWNLOAD_REMOVED: { - BWebDownload* download; - if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) - downloadFinished(download); - break; - } - case REMOVE_FINISHED_DOWNLOADS: - removeFinishedDownloads(); - break; - case SAVE_SETTINGS: - saveSettings(); - break; - default: - BWindow::MessageReceived(message); - break; - } + switch (message->what) { + case B_DOWNLOAD_ADDED: { + BWebDownload* download; + if (message->FindPointer("download", reinterpret_cast( + &download)) == B_OK) { + _DownloadStarted(download); + } + break; + } + case B_DOWNLOAD_REMOVED: { + BWebDownload* download; + if (message->FindPointer("download", reinterpret_cast( + &download)) == B_OK) { + _DownloadFinished(download); + } + break; + } + case REMOVE_FINISHED_DOWNLOADS: + _RemoveFinishedDownloads(); + break; + case SAVE_SETTINGS: + _SaveSettings(); + break; + default: + BWindow::MessageReceived(message); + break; + } } -bool DownloadWindow::QuitRequested() + +bool +DownloadWindow::QuitRequested() { if (!IsHidden()) - Hide(); - return false; + Hide(); + return false; } -void DownloadWindow::downloadStarted(BWebDownload* download) + +void +DownloadWindow::_DownloadStarted(BWebDownload* download) { int32 finishedCount = 0; int32 index = 0; - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (view->url() == download->URL()) { - index = i; - view->RemoveSelf(); - delete view; - } else if (!view->download()) - finishedCount++; + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->URL() == download->URL()) { + index = i; + view->RemoveSelf(); + delete view; + } else if (!view->Download()) + finishedCount++; } - m_removeFinishedButton->SetEnabled(finishedCount > 0); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); - if (!view->init()) + if (!view->Init()) return; - m_downloadViewsLayout->AddView(index, view); - saveSettings(); + fDownloadViewsLayout->AddView(index, view); + _SaveSettings(); SetWorkspaces(B_CURRENT_WORKSPACE); if (IsHidden()) Show(); } -void DownloadWindow::downloadFinished(BWebDownload* download) + +void +DownloadWindow::_DownloadFinished(BWebDownload* download) { int32 finishedCount = 0; - for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (view->download() == download) { - view->downloadFinished(); - finishedCount++; - } else if (!view->download()) - finishedCount++; + for (int32 i = 0; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i++) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->Download() == download) { + view->DownloadFinished(); + finishedCount++; + } else if (!view->Download()) + finishedCount++; } - m_removeFinishedButton->SetEnabled(finishedCount > 0); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); if (download) - saveSettings(); + _SaveSettings(); } -void DownloadWindow::removeFinishedDownloads() + +void +DownloadWindow::_RemoveFinishedDownloads() { - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (!view->download()) { - view->RemoveSelf(); - delete view; - } + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (!view->Download()) { + view->RemoveSelf(); + delete view; + } } - m_removeFinishedButton->SetEnabled(false); - saveSettings(); + fRemoveFinishedButton->SetEnabled(false); + _SaveSettings(); } -void DownloadWindow::saveSettings() + +void +DownloadWindow::_SaveSettings() { BFile file; - if (!openSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) - return; + if (!_OpenSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) + return; BMessage message; - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - BMessage downloadArchive; - if (view->saveSettings(&downloadArchive) == B_OK) - message.AddMessage("download", &downloadArchive); + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + BMessage downloadArchive; + if (view->SaveSettings(&downloadArchive) == B_OK) + message.AddMessage("download", &downloadArchive); } message.Flatten(&file); } -void DownloadWindow::loadSettings() + +void +DownloadWindow::_LoadSettings() { BFile file; - if (!openSettingsFile(file, B_READ_ONLY)) - return; + 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)) + 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; - m_downloadViewsLayout->AddView(0, view); + fDownloadViewsLayout->AddView(0, view); } } -bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) + +bool +DownloadWindow::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index c7819ffdec..c901b2dda7 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -24,9 +24,9 @@ * (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 -#ifndef DownloadWindow_h -#define DownloadWindow_h #include @@ -35,26 +35,27 @@ class BFile; class BGroupLayout; class BWebDownload; + class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); - virtual ~DownloadWindow(); + DownloadWindow(BRect frame, bool visible); + virtual ~DownloadWindow(); - virtual void MessageReceived(BMessage*); - virtual bool QuitRequested(); + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); private: - void downloadStarted(BWebDownload* download); - void downloadFinished(BWebDownload* download); - void removeFinishedDownloads(); - void saveSettings(); - void loadSettings(); - bool openSettingsFile(BFile& file, uint32 mode); + void _DownloadStarted(BWebDownload* download); + void _DownloadFinished(BWebDownload* download); + void _RemoveFinishedDownloads(); + void _SaveSettings(); + void _LoadSettings(); + bool _OpenSettingsFile(BFile& file, uint32 mode); private: - BGroupLayout* m_downloadViewsLayout; - BButton* m_removeFinishedButton; + BGroupLayout* fDownloadViewsLayout; + BButton* fRemoveFinishedButton; }; -#endif // DownloadWindow_h +#endif // DOWNLOAD_WINDOW_H From 0ba16dd4c1bde479b0e91162f63b163858d3dd82 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:04:31 +0000 Subject: [PATCH 120/293] Added support for attaching listeners to the SettingsMessage, to be notified when a named value changes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@338 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/SettingsMessage.cpp | 188 ++++++++++++++---- .../webpositive/support/SettingsMessage.h | 18 +- 2 files changed, 161 insertions(+), 45 deletions(-) diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index 98e9ef1c94..d96ceb1e64 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -9,14 +9,19 @@ #include "SettingsMessage.h" +#include + #include #include +#include #include SettingsMessage::SettingsMessage(directory_which directory, const char* filename) - : BMessage('pref') + : + BMessage('pref'), + fListeners(4) { fStatus = find_directory(directory, &fPath); @@ -31,6 +36,9 @@ SettingsMessage::SettingsMessage(directory_which directory, SettingsMessage::~SettingsMessage() { Save(); + + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) + delete reinterpret_cast(fListeners.ItemAtFast(i)); } @@ -67,139 +75,212 @@ SettingsMessage::Save() const } +bool +SettingsMessage::AddListener(const BMessenger& listener) +{ + BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); + if (listenerCopy && fListeners.AddItem(listenerCopy)) + return true; + delete listenerCopy; + return false; +} + + +void +SettingsMessage::RemoveListener(const BMessenger& listener) +{ + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { + BMessenger* listenerItem = reinterpret_cast( + fListeners.ItemAtFast(i)); + if (*listenerItem == listener) { + fListeners.RemoveItem(i); + delete listenerItem; + return; + } + } +} + + // #pragma mark - status_t SettingsMessage::SetValue(const char* name, bool value) { - if (ReplaceBool(name, value) == B_OK) - return B_OK; - return AddBool(name, 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) { - if (ReplaceInt8(name, value) == B_OK) - return B_OK; - return AddInt8(name, 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) { - if (ReplaceInt16(name, value) == B_OK) - return B_OK; - return AddInt16(name, 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) { - if (ReplaceInt32(name, value) == B_OK) - return B_OK; - return AddInt32(name, 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) { - if (ReplaceInt32(name, (int32)value) == B_OK) - return B_OK; - return AddInt32(name, (int32)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) { - if (ReplaceInt64(name, value) == B_OK) - return B_OK; - return AddInt64(name, 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) { - if (ReplaceFloat(name, value) == B_OK) - return B_OK; - return AddFloat(name, 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) { - if (ReplaceDouble(name, value) == B_OK) - return B_OK; - return AddDouble(name, 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) { - if (ReplaceString(name, value) == B_OK) - return B_OK; - return AddString(name, 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) { - return SetValue(name, value.String()); + 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) { - if (ReplacePoint(name, value) == B_OK) - return B_OK; - return AddPoint(name, 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) { - if (ReplaceRect(name, value) == B_OK) - return B_OK; - return AddRect(name, 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) { - if (ReplaceRef(name, &value) == B_OK) - return B_OK; - return AddRef(name, &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) { - if (ReplaceMessage(name, &value) == B_OK) - return B_OK; - return AddMessage(name, &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) { - if (ReplaceFlat(name, const_cast(value)) == B_OK) - return B_OK; - return AddFlat(name, const_cast(value)); + status_t ret = ReplaceFlat(name, const_cast(value)); + if (ret != B_OK) + ret = AddFlat(name, const_cast(value)); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } @@ -221,6 +302,8 @@ SettingsMessage::SetValue(const char* name, const BFont& value) if (ReplaceMessage(name, &fontMessage) != B_OK) ret = AddMessage(name, &fontMessage); } + if (ret == B_OK) + _NotifyValueChanged(name); return ret; } @@ -383,3 +466,20 @@ SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const return value; } + +// #pragma mark - private + + +void +SettingsMessage::_NotifyValueChanged(const char* name) const +{ + BMessage message(MSG_SETTINGS_VALUE_CHANGED); + message.AddString("name", name); + int32 count = fListeners.CountItems(); + for (int32 i = 0; i < count; i++) { + BMessenger* listener = reinterpret_cast( + fListeners.ItemAtFast(i)); + listener->SendMessage(&message); + } +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index 8420238be8..b4d37e6009 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Stephan Aßmus . + * Copyright 2008-2010 Stephan Aßmus . * Copyright 1998 Eric Shepherd. * All rights reserved. Distributed under the terms of the Be Sample Code * license. @@ -7,13 +7,22 @@ #ifndef SETTINGS_MESSAGE_H #define SETTINGS_MESSAGE_H + #include #include +#include #include #include +class BMessenger; class BString; + +enum { + MSG_SETTINGS_VALUE_CHANGED = 'stvc' +}; + + class SettingsMessage : public BMessage { public: SettingsMessage(directory_which directory, @@ -25,6 +34,9 @@ public: 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); @@ -76,9 +88,13 @@ public: 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 From 6463044ee7867e256bb409283a463a0055979769 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:10:49 +0000 Subject: [PATCH 121/293] Add the value to the notification message as well. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@339 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.h | 5 ++++- src/apps/webpositive/support/SettingsMessage.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index c901b2dda7..be0e84da6b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,11 +34,13 @@ class BButton; class BFile; class BGroupLayout; class BWebDownload; +class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); + DownloadWindow(BRect frame, bool visible, + SettingsMessage* settings); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -55,6 +57,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + SettingsMessage* fSettings; }; diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index d96ceb1e64..de17c8d3a4 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -475,6 +475,16 @@ SettingsMessage::_NotifyValueChanged(const char* name) const { BMessage message(MSG_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( From 1beb8c80351e03b8ab4920ce9cd822ec4624f4a0 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:11:27 +0000 Subject: [PATCH 122/293] Whoops... should not have been part of the commit... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@340 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index be0e84da6b..571c7f303b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,13 +34,11 @@ class BButton; class BFile; class BGroupLayout; class BWebDownload; -class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible, - SettingsMessage* settings); + DownloadWindow(BRect frame, bool visible); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -57,8 +55,6 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; - SettingsMessage* fSettings; }; - #endif // DOWNLOAD_WINDOW_H From 636f175b1500fc2bbaf462d29f46af8c6d0ee0b9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 00:02:05 +0000 Subject: [PATCH 123/293] Work in progress on better download management... * Allow to specify the downloads folder in the General settings page. * Added necessary wiring. * The listener notification was not synchronous anymore because of mixed up default function params in BWebPage. * Added temporary debug output to WebDownloadPrivate.cpp... the restarting downloads code path needs testing yet. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@341 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 3 +- src/apps/webpositive/DownloadWindow.cpp | 75 ++++++++++++++----- src/apps/webpositive/DownloadWindow.h | 6 +- src/apps/webpositive/SettingsWindow.cpp | 27 ++++--- .../webpositive/support/SettingsMessage.cpp | 21 +++++- .../webpositive/support/SettingsMessage.h | 13 +++- 6 files changed, 109 insertions(+), 36 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 7bbb63c633..db118555b5 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -145,7 +145,8 @@ BrowserApp::ReadyToRun() BRect()); bool showDownloads = fSettings->GetValue("show downloads", false); - fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads, + fSettings); fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); BWebPage::SetDownloadListener(BMessenger(fDownloadWindow)); diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index f852cb6f2e..6eb6f0c45c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -48,6 +48,7 @@ #include #include "BrowserApp.h" +#include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -64,15 +65,13 @@ enum { class IconView : public BView { public: - IconView(const BEntry& entry) + IconView() : BView("Download icon", B_WILL_DRAW), fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) { - BNode node(&entry); - BNodeInfo info(&node); - info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); SetDrawingMode(B_OP_OVER); + memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); } IconView(BMessage* archive) @@ -83,6 +82,14 @@ public: SetDrawingMode(B_OP_OVER); } + void SetTo(const BEntry& entry) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); + Invalidate(); + } + status_t SaveSettings(BMessage* archive) { return fIconBitmap.Archive(archive); @@ -162,27 +169,24 @@ public: bool Init(BMessage* archive = NULL) { - BEntry entry(fPath.Path()); - if (!entry.Exists() && !archive) - return false; - SetViewColor(245, 245, 245); SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); BGridLayout* layout = GridLayout(); - fStatusBar = new BStatusBar("download progress", fPath.Leaf()); - fStatusBar->SetMaxValue(100); 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); - if (entry.Exists()) - fIconView = new IconView(entry); - else + if (archive) fIconView = new IconView(archive); + else + fIconView = new IconView(); if (!fDownload && fStatusBar->CurrentValue() < 100) fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); @@ -247,6 +251,17 @@ public: virtual void 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); +printf("B_DOWNLOAD_STARTED: %s\n", fPath.Leaf()); + fStatusBar->Reset(fPath.Leaf()); + break; + }; case B_DOWNLOAD_PROGRESS: { float progress; if (message->FindFloat("progress", &progress) == B_OK) @@ -391,11 +406,22 @@ protected: }; -DownloadWindow::DownloadWindow(BRect frame, bool visible) +// #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) { + settings->AddListener(BMessenger(this)); + BPath downloadPath; + if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) + downloadPath.SetTo("/boot/home/Desktop"); + fDownloadPath = settings->GetValue("download path", downloadPath.Path()); + settings->SetValue("download path", fDownloadPath); + SetLayout(new BGroupLayout(B_VERTICAL)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); @@ -445,7 +471,8 @@ void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { - case B_DOWNLOAD_ADDED: { + case B_DOWNLOAD_ADDED: + { BWebDownload* download; if (message->FindPointer("download", reinterpret_cast( &download)) == B_OK) { @@ -453,7 +480,8 @@ DownloadWindow::MessageReceived(BMessage* message) } break; } - case B_DOWNLOAD_REMOVED: { + case B_DOWNLOAD_REMOVED: + { BWebDownload* download; if (message->FindPointer("download", reinterpret_cast( &download)) == B_OK) { @@ -467,6 +495,17 @@ DownloadWindow::MessageReceived(BMessage* message) case SAVE_SETTINGS: _SaveSettings(); break; + + case SETTINGS_VALUE_CHANGED: + { + BString string; + if (message->FindString("name", &string) == B_OK + && string == "download path" + && message->FindString("value", &string) == B_OK) { + fDownloadPath = string; + } + break; + } default: BWindow::MessageReceived(message); break; @@ -486,6 +525,8 @@ DownloadWindow::QuitRequested() void DownloadWindow::_DownloadStarted(BWebDownload* download) { + download->Start(BPath(fDownloadPath.String())); + int32 finishedCount = 0; int32 index = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 571c7f303b..bf7365e1ee 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -28,17 +28,20 @@ #define DOWNLOAD_WINDOW_H +#include #include class BButton; class BFile; class BGroupLayout; class BWebDownload; +class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); + DownloadWindow(BRect frame, bool visible, + SettingsMessage* settings); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -55,6 +58,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + BString fDownloadPath; }; #endif // DOWNLOAD_WINDOW_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index e240147f2d..833924b7a2 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -202,7 +202,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); -fDownloadFolderControl->SetEnabled(false); + fDownloadFolderControl->SetText(fSettings->GetValue("download path", "")); fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), NULL); @@ -312,7 +312,20 @@ SettingsWindow::_CreateFontsPage(float spacing) void SettingsWindow::_ApplySettings() { - // Store settings + // Store general settings + int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + if (maxHistoryAge <= 0) + maxHistoryAge = 1; + if (maxHistoryAge >= 35) + maxHistoryAge = 35; + BString text; + text << maxHistoryAge; + fDaysInGoMenuControl->SetText(text.String()); + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); + + fSettings->SetValue("download path", fDownloadFolderControl->Text()); + + // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); fSettings->SetValue("serif font", fSerifFontView->Font()); fSettings->SetValue("sans serif font", fSansSerifFontView->Font()); @@ -335,16 +348,6 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); - - int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); - if (maxHistoryAge <= 0) - maxHistoryAge = 1; - if (maxHistoryAge >= 35) - maxHistoryAge = 35; - BString text; - text << maxHistoryAge; - fDaysInGoMenuControl->SetText(text.String()); - BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); } diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index de17c8d3a4..e11900b1b5 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -52,6 +53,8 @@ SettingsMessage::InitCheck() const status_t SettingsMessage::Load() { + BAutolock _(this); + BFile file(fPath.Path(), B_READ_ONLY); status_t status = file.InitCheck(); @@ -65,6 +68,8 @@ SettingsMessage::Load() status_t SettingsMessage::Save() const { + BAutolock _(const_cast(this)); + BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); status_t status = file.InitCheck(); @@ -78,6 +83,8 @@ SettingsMessage::Save() const bool SettingsMessage::AddListener(const BMessenger& listener) { + BAutolock _(this); + BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); if (listenerCopy && fListeners.AddItem(listenerCopy)) return true; @@ -89,6 +96,8 @@ SettingsMessage::AddListener(const BMessenger& listener) void SettingsMessage::RemoveListener(const BMessenger& listener) { + BAutolock _(this); + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { BMessenger* listenerItem = reinterpret_cast( fListeners.ItemAtFast(i)); @@ -401,6 +410,16 @@ SettingsMessage::GetValue(const char* name, const BString& defaultValue) const } +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 { @@ -473,7 +492,7 @@ SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const void SettingsMessage::_NotifyValueChanged(const char* name) const { - BMessage message(MSG_SETTINGS_VALUE_CHANGED); + BMessage message(SETTINGS_VALUE_CHANGED); message.AddString("name", name); // Add the value of that name to the notification. diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index b4d37e6009..bf2822dd8e 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -19,11 +20,11 @@ class BString; enum { - MSG_SETTINGS_VALUE_CHANGED = 'stvc' + SETTINGS_VALUE_CHANGED = '_svc' }; -class SettingsMessage : public BMessage { +class SettingsMessage : public BMessage, public BLocker { public: SettingsMessage(directory_which directory, const char* filename); @@ -49,9 +50,11 @@ public: 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 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 entry_ref& value); status_t SetValue(const char* name, const BMessage& value); status_t SetValue(const char* name, @@ -75,6 +78,8 @@ public: 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, From 0430f93fe3647138259f4207515c1a58ad00765c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 13:06:33 +0000 Subject: [PATCH 124/293] * Finished testing of downloads interaction with listener and removed debug output. * Optimized download restoration at program start and moved it into download window thread in order not to block app startup. * Downloads which have been removed meanwhile, are displayed with dimmed icon, and the option to Restart it is given. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@342 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 81 +++++++++++++++++++++---- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 6eb6f0c45c..40f8312af3 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -54,6 +54,8 @@ enum { + INIT = 'init', + OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', OPEN_DOWNLOAD = 'opdn', RESTART_DOWNLOAD = 'rsdn', @@ -65,10 +67,21 @@ enum { 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) + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), + fDimmedIcon(false) { SetDrawingMode(B_OP_OVER); memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); @@ -77,7 +90,8 @@ public: IconView(BMessage* archive) : BView("Download icon", B_WILL_DRAW), - fIconBitmap(archive) + fIconBitmap(archive), + fDimmedIcon(true) { SetDrawingMode(B_OP_OVER); } @@ -90,6 +104,14 @@ public: Invalidate(); } + void SetIconDimmed(bool iconDimmed) + { + if (fDimmedIcon != iconDimmed) { + fDimmedIcon = iconDimmed; + Invalidate(); + } + } + status_t SaveSettings(BMessage* archive) { return fIconBitmap.Archive(archive); @@ -102,6 +124,11 @@ public: 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); } @@ -121,7 +148,8 @@ public: } private: - BBitmap fIconBitmap; + BBitmap fIconBitmap; + bool fDimmedIcon; }; @@ -183,12 +211,18 @@ public: fStatusBar->SetMaxValue(100); fStatusBar->SetBarHeight(12); - if (archive) - fIconView = new IconView(archive); - else + // 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) + if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists())) fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); else { fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); @@ -258,7 +292,6 @@ public: fPath.SetTo(path); BEntry entry(fPath.Path()); fIconView->SetTo(entry); -printf("B_DOWNLOAD_STARTED: %s\n", fPath.Leaf()); fStatusBar->Reset(fPath.Leaf()); break; }; @@ -428,7 +461,9 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, fDownloadViewsLayout = downloadsGroupView->GroupLayout(); BMenuBar* menuBar = new BMenuBar("Menu bar"); - BMenu* menu = new BMenu("Window"); + BMenu* menu = new BMenu("Downloads"); + menu->AddItem(new BMenuItem("Open downloads folder", + new BMessage(OPEN_DOWNLOADS_FOLDER))); menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); @@ -450,9 +485,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, ) ); - _LoadSettings(); - // Small trick to get the correct enabled status of the Remove finished button - _DownloadFinished(NULL); + PostMessage(INIT); if (!visible) Hide(); @@ -471,6 +504,14 @@ 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; @@ -489,6 +530,22 @@ DownloadWindow::MessageReceived(BMessage* message) } 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; From 2e70c4bf9b51331438ac7fc48f116b7f0479ec18 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 13:17:03 +0000 Subject: [PATCH 125/293] Adjust the steps of the downloads window scrollbar. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@343 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 40f8312af3..aa54a4ee7c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -435,6 +435,11 @@ protected: 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); + } } }; From 61c96f4e5ef25a9b1a14aa9486a8a66bcf461bcc Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 14:00:13 +0000 Subject: [PATCH 126/293] Added node monitoring to downloads window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@344 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 84 +++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index aa54a4ee7c..0a4fa8fd58 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,15 @@ public: fDownload->SetProgressListener(BMessenger(this)); fTopButton->SetTarget(this); fBottomButton->SetTarget(this); + + BEntry entry(fPath.Path()); + if (entry.Exists()) + _StartNodeMonitor(entry); + } + + virtual void DetachedFromWindow() + { + _StopNodeMonitor(); } virtual void AllAttached() @@ -285,7 +295,8 @@ public: virtual void MessageReceived(BMessage* message) { switch (message->what) { - case B_DOWNLOAD_STARTED: { + case B_DOWNLOAD_STARTED: + { BString path; if (message->FindString("path", &path) != B_OK) break; @@ -293,15 +304,18 @@ public: BEntry entry(fPath.Path()); fIconView->SetTo(entry); fStatusBar->Reset(fPath.Leaf()); + _StartNodeMonitor(entry); break; }; - case B_DOWNLOAD_PROGRESS: { + case B_DOWNLOAD_PROGRESS: + { float progress; if (message->FindFloat("progress", &progress) == B_OK) fStatusBar->SetTo(progress); break; } - case OPEN_DOWNLOAD: { + 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); @@ -323,7 +337,8 @@ public: DownloadCanceled(); break; - case REMOVE_DOWNLOAD: { + case REMOVE_DOWNLOAD: + { Window()->PostMessage(SAVE_SETTINGS); RemoveSelf(); delete this; @@ -336,6 +351,54 @@ public: // at the window... Window()->PostMessage(message); break; + 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: + { + int64 fromDirectory; + int64 toDirectory; + if (message->FindInt64("from directory", + &fromDirectory) != B_OK + || message->FindInt64("to directory", + &toDirectory) != B_OK) { + break; + } + if (fromDirectory == toDirectory) { + // Entry was renamed + const char* name; + if (message->FindString("name", &name) != B_OK + || strlen(name) == 0) { + break; + } + fPath.GetParent(&fPath); + fPath.Append(name); + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); + } else { + // Entry was moved elsewhere + fIconView->SetIconDimmed(true); + DownloadCanceled(); + } + break; + } + case B_ATTR_CHANGED: + { + BEntry entry(fPath.Path()); + fIconView->SetIconDimmed(false); + fIconView->SetTo(entry); + break; + } + } + break; + } default: BGridView::MessageReceived(message); } @@ -371,6 +434,19 @@ public: fBottomButton->SetEnabled(true); } +private: + void _StartNodeMonitor(const BEntry& entry) + { + node_ref nref; + if (entry.GetNodeRef(&nref) == B_OK) + watch_node(&nref, B_WATCH_ALL, this); + } + + void _StopNodeMonitor() + { + stop_watching(this); + } + private: IconView* fIconView; BStatusBar* fStatusBar; From b65e0ec04eda1f31059cdac01cf99c9d447bb217 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 14:48:58 +0000 Subject: [PATCH 127/293] Just follow a moved download file, as Axel suggested. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@345 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 30 ++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0a4fa8fd58..b9039636cc 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -363,29 +363,23 @@ public: break; case B_ENTRY_MOVED: { - int64 fromDirectory; - int64 toDirectory; - if (message->FindInt64("from directory", - &fromDirectory) != B_OK + // Follow the entry to the new location + dev_t device; + ino_t directory; + const char* name; + if (message->FindInt32("device", + reinterpret_cast(&device)) != B_OK || message->FindInt64("to directory", - &toDirectory) != B_OK) { + reinterpret_cast(&directory)) != B_OK + || message->FindString("name", &name) != B_OK + || strlen(name) == 0) { break; } - if (fromDirectory == toDirectory) { - // Entry was renamed - const char* name; - if (message->FindString("name", &name) != B_OK - || strlen(name) == 0) { - break; - } - fPath.GetParent(&fPath); - fPath.Append(name); + entry_ref ref(device, directory, name); + BEntry entry(&ref); + if (entry.GetPath(&fPath) == B_OK) { fStatusBar->SetText(name); Window()->PostMessage(SAVE_SETTINGS); - } else { - // Entry was moved elsewhere - fIconView->SetIconDimmed(true); - DownloadCanceled(); } break; } From f28abe9d244e9b3b58c3bf988e44430f99092610 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:11:29 +0000 Subject: [PATCH 128/293] * An unfinished download is no longer considered finished, just because it isn't currently in progress anymore. * Added feature to remove "missing" downloads, i.e. those for which no corresponding file exists. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@346 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 63 +++++++++++++++++++++++-- src/apps/webpositive/DownloadWindow.h | 2 + 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b9039636cc..ae60ac4f5f 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -58,6 +58,7 @@ enum { INIT = 'init', OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', + REMOVE_MISSING_DOWNLOADS = 'rmmd', OPEN_DOWNLOAD = 'opdn', RESTART_DOWNLOAD = 'rsdn', CANCEL_DOWNLOAD = 'cndn', @@ -112,6 +113,11 @@ public: Invalidate(); } } + + bool IsIconDimmed() const + { + return fDimmedIcon; + } status_t SaveSettings(BMessage* archive) { @@ -408,6 +414,16 @@ public: return fURL; } + bool IsMissing() const + { + return fIconView->IsIconDimmed(); + } + + bool IsFinished() const + { + return !fDownload && fStatusBar->CurrentValue() == 100; + } + void DownloadFinished() { fDownload = NULL; @@ -549,12 +565,17 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, new BMessage(REMOVE_FINISHED_DOWNLOADS)); fRemoveFinishedButton->SetEnabled(false); + fRemoveMissingButton = new BButton("Remove missing", + new BMessage(REMOVE_MISSING_DOWNLOADS)); + fRemoveMissingButton->SetEnabled(false); + AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) .Add(scrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL) .AddGlue() + .Add(fRemoveMissingButton) .Add(fRemoveFinishedButton) .SetInsets(5, 5, 5, 5) ) @@ -624,6 +645,9 @@ DownloadWindow::MessageReceived(BMessage* message) case REMOVE_FINISHED_DOWNLOADS: _RemoveFinishedDownloads(); break; + case REMOVE_MISSING_DOWNLOADS: + _RemoveMissingDownloads(); + break; case SAVE_SETTINGS: _SaveSettings(); break; @@ -660,6 +684,7 @@ 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--) { @@ -671,10 +696,15 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) index = i; view->RemoveSelf(); delete view; - } else if (!view->Download()) + 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()) return; @@ -691,19 +721,25 @@ 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( item->View()); if (!view) continue; - if (view->Download() == download) { + if (download && view->Download() == download) { view->DownloadFinished(); finishedCount++; - } else if (!view->Download()) + continue; + } + if (view->IsFinished()) finishedCount++; + if (view->IsMissing()) + missingCount++; } fRemoveFinishedButton->SetEnabled(finishedCount > 0); + fRemoveMissingButton->SetEnabled(missingCount > 0); if (download) _SaveSettings(); } @@ -718,7 +754,7 @@ DownloadWindow::_RemoveFinishedDownloads() item->View()); if (!view) continue; - if (!view->Download()) { + if (view->IsFinished()) { view->RemoveSelf(); delete view; } @@ -728,6 +764,25 @@ DownloadWindow::_RemoveFinishedDownloads() } +void +DownloadWindow::_RemoveMissingDownloads() +{ + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->IsMissing()) { + view->RemoveSelf(); + delete view; + } + } + fRemoveMissingButton->SetEnabled(false); + _SaveSettings(); +} + + void DownloadWindow::_SaveSettings() { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index bf7365e1ee..3275620293 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -51,6 +51,7 @@ private: void _DownloadStarted(BWebDownload* download); void _DownloadFinished(BWebDownload* download); void _RemoveFinishedDownloads(); + void _RemoveMissingDownloads(); void _SaveSettings(); void _LoadSettings(); bool _OpenSettingsFile(BFile& file, uint32 mode); @@ -58,6 +59,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + BButton* fRemoveMissingButton; BString fDownloadPath; }; From f65c57d54eca61c834926836f25da9ab9f7f8c46 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:13:56 +0000 Subject: [PATCH 129/293] Removing finished or missing downloads may have to disable the respective other button. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@347 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ae60ac4f5f..c22a8602cc 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -748,6 +748,7 @@ DownloadWindow::_DownloadFinished(BWebDownload* download) void DownloadWindow::_RemoveFinishedDownloads() { + int32 missingCount = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { DownloadProgressView* view = dynamic_cast( @@ -757,9 +758,11 @@ DownloadWindow::_RemoveFinishedDownloads() if (view->IsFinished()) { view->RemoveSelf(); delete view; - } + } else if (view->IsMissing()) + missingCount++; } fRemoveFinishedButton->SetEnabled(false); + fRemoveMissingButton->SetEnabled(missingCount > 0); _SaveSettings(); } @@ -767,6 +770,7 @@ DownloadWindow::_RemoveFinishedDownloads() void DownloadWindow::_RemoveMissingDownloads() { + int32 finishedCount = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { DownloadProgressView* view = dynamic_cast( @@ -776,9 +780,11 @@ DownloadWindow::_RemoveMissingDownloads() if (view->IsMissing()) { view->RemoveSelf(); delete view; - } + } else if (view->IsFinished()) + finishedCount++; } fRemoveMissingButton->SetEnabled(false); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); _SaveSettings(); } From 34c5cb8c83b6ad9111c2d7649dc040a96aac2f44 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:37:01 +0000 Subject: [PATCH 130/293] Following another suggestion by Axel: Check if a download file is being moved into the trash. If it's still in progress, cancel it. Dim the icon in any case. Undim the icon if a download is moved back out of the trash (restarting still has to happen manually). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@348 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index c22a8602cc..ad0b6d90a5 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -381,12 +382,36 @@ public: || 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) { - fStatusBar->SetText(name); - Window()->PostMessage(SAVE_SETTINGS); + 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); + } } + + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); break; } case B_ATTR_CHANGED: From 7ac6b59c333c879894c189812643e5e2a8768eb2 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 18:41:38 +0000 Subject: [PATCH 131/293] Moved DownloadProgressView and related private classes out into their own source file. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@350 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 504 ++++++++++++++++++ src/apps/webpositive/DownloadProgressView.h | 86 +++ src/apps/webpositive/DownloadWindow.cpp | 441 +-------------- 3 files changed, 593 insertions(+), 438 deletions(-) create mode 100644 src/apps/webpositive/DownloadProgressView.cpp create mode 100644 src/apps/webpositive/DownloadProgressView.h diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp new file mode 100644 index 0000000000..bedbc67bad --- /dev/null +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "WebDownload.h" +#include "WebPage.h" + + +enum { + OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', + REMOVE_DOWNLOAD = 'rmdn', +}; + + +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) + : + BGridView(8, 3), + fDownload(download), + fURL(download->URL()), + fPath(download->Path()), + fExpectedSize(download->ExpectedSize()) +{ +} + + +DownloadProgressView::DownloadProgressView(const BMessage* archive) + : + BGridView(8, 3), + fDownload(NULL), + fURL(), + fPath(), + fExpectedSize(0) +{ + 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) +{ + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + + BGridLayout* layout = GridLayout(); + 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); + } + + layout->SetInsets(8, 5, 5, 6); + layout->AddView(fIconView, 0, 0, 1, 2); + layout->AddView(fStatusBar, 1, 0, 1, 2); + layout->AddView(fTopButton, 2, 0); + layout->AddView(fBottomButton, 2, 1); + + 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)); + fTopButton->SetTarget(this); + fBottomButton->SetTarget(this); + + BEntry entry(fPath.Path()); + if (entry.Exists()) + _StartNodeMonitor(entry); +} + + +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); + break; + }; + case B_DOWNLOAD_PROGRESS: + { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + fStatusBar->SetTo(progress); + 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_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 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(&device)) != B_OK + || message->FindInt64("to directory", + reinterpret_cast(&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); + } + } + + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); + break; + } + case B_ATTR_CHANGED: + { + BEntry entry(fPath.Path()); + fIconView->SetIconDimmed(false); + fIconView->SetTo(entry); + break; + } + } + break; + } + default: + BGridView::MessageReceived(message); + } +} + + +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; + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); +} + + +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); +} + + +// #pragma mark - private + + +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); +} + diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h new file mode 100644 index 0000000000..d39ca93380 --- /dev/null +++ b/src/apps/webpositive/DownloadProgressView.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include +#include + +class BEntry; +class BStatusBar; +class BWebDownload; +class IconView; +class SmallButton; + + +enum { + SAVE_SETTINGS = 'svst' +}; + + +class DownloadProgressView : public BGridView { +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); + + BWebDownload* Download() const; + const BString& URL() const; + bool IsMissing() const; + bool IsFinished() const; + + void DownloadFinished(); + void DownloadCanceled(); + +private: + void _StartNodeMonitor(const BEntry& entry); + void _StopNodeMonitor(); + +private: + IconView* fIconView; + BStatusBar* fStatusBar; + SmallButton* fTopButton; + SmallButton* fBottomButton; + BWebDownload* fDownload; + BString fURL; + BPath fPath; + off_t fExpectedSize; +}; + +#endif // DOWNLOAD_PROGRESS_VIEW_H diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ad0b6d90a5..a2f3f38aff 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,26 +30,22 @@ #include #include -#include #include -#include #include +#include #include -#include #include #include #include #include -#include -#include #include #include #include #include #include -#include #include "BrowserApp.h" +#include "DownloadProgressView.h" #include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -59,438 +55,7 @@ enum { INIT = 'init', OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', - REMOVE_MISSING_DOWNLOADS = 'rmmd', - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', - SAVE_SETTINGS = 'svst' -}; - - -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); - } -}; - - -class DownloadProgressView : public BGridView { -public: - DownloadProgressView(BWebDownload* download) - : - BGridView(8, 3), - fDownload(download), - fURL(download->URL()), - fPath(download->Path()), - fExpectedSize(download->ExpectedSize()) - { - } - - DownloadProgressView(const BMessage* archive) - : - BGridView(8, 3), - fDownload(NULL), - fURL(), - fPath(), - fExpectedSize(0) - { - const char* string; - if (archive->FindString("path", &string) == B_OK) - fPath.SetTo(string); - if (archive->FindString("url", &string) == B_OK) - fURL = string; - } - - bool Init(BMessage* archive = NULL) - { - SetViewColor(245, 245, 245); - SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); - - BGridLayout* layout = GridLayout(); - 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); - } - - layout->SetInsets(8, 5, 5, 6); - layout->AddView(fIconView, 0, 0, 1, 2); - layout->AddView(fStatusBar, 1, 0, 1, 2); - layout->AddView(fTopButton, 2, 0); - layout->AddView(fBottomButton, 2, 1); - - return true; - } - - status_t 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; - } - - virtual void AttachedToWindow() - { - if (fDownload) - fDownload->SetProgressListener(BMessenger(this)); - fTopButton->SetTarget(this); - fBottomButton->SetTarget(this); - - BEntry entry(fPath.Path()); - if (entry.Exists()) - _StartNodeMonitor(entry); - } - - virtual void DetachedFromWindow() - { - _StopNodeMonitor(); - } - - virtual void AllAttached() - { - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(245, 245, 245); - SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - bounds.bottom--; - FillRect(bounds, B_SOLID_LOW); - bounds.bottom++; - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - } - - virtual void 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); - break; - }; - case B_DOWNLOAD_PROGRESS: - { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - fStatusBar->SetTo(progress); - 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_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 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(&device)) != B_OK - || message->FindInt64("to directory", - reinterpret_cast(&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); - } - } - - fStatusBar->SetText(name); - Window()->PostMessage(SAVE_SETTINGS); - break; - } - case B_ATTR_CHANGED: - { - BEntry entry(fPath.Path()); - fIconView->SetIconDimmed(false); - fIconView->SetTo(entry); - break; - } - } - break; - } - default: - BGridView::MessageReceived(message); - } - } - - BWebDownload* Download() const - { - return fDownload; - } - - const BString& URL() const - { - return fURL; - } - - bool IsMissing() const - { - return fIconView->IsIconDimmed(); - } - - bool IsFinished() const - { - return !fDownload && fStatusBar->CurrentValue() == 100; - } - - void DownloadFinished() - { - fDownload = NULL; - fTopButton->SetEnabled(true); - fBottomButton->SetLabel("Remove"); - fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - fBottomButton->SetEnabled(true); - } - - void 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); - } - -private: - void _StartNodeMonitor(const BEntry& entry) - { - node_ref nref; - if (entry.GetNodeRef(&nref) == B_OK) - watch_node(&nref, B_WATCH_ALL, this); - } - - void _StopNodeMonitor() - { - stop_watching(this); - } - -private: - IconView* fIconView; - BStatusBar* fStatusBar; - SmallButton* fTopButton; - SmallButton* fBottomButton; - BWebDownload* fDownload; - BString fURL; - BPath fPath; - off_t fExpectedSize; + REMOVE_MISSING_DOWNLOADS = 'rmmd' }; From 799888211608ea8a3bed35e72d4f24e4da25f6ca Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:19:40 +0000 Subject: [PATCH 132/293] Imported StringForSize utility function from Haiku. To be removed when WebPositive is integrated into the Haiku source tree. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@351 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/StringForSize.cpp | 43 +++++++++++++++++++ src/apps/webpositive/support/StringForSize.h | 23 ++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/apps/webpositive/support/StringForSize.cpp create mode 100644 src/apps/webpositive/support/StringForSize.h diff --git a/src/apps/webpositive/support/StringForSize.cpp b/src/apps/webpositive/support/StringForSize.cpp new file mode 100644 index 0000000000..ae7831e397 --- /dev/null +++ b/src/apps/webpositive/support/StringForSize.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "StringForSize.h" + +#include + + +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 + diff --git a/src/apps/webpositive/support/StringForSize.h b/src/apps/webpositive/support/StringForSize.h new file mode 100644 index 0000000000..fa3e13b115 --- /dev/null +++ b/src/apps/webpositive/support/StringForSize.h @@ -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 + + +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 From 90ac9c309c2294577ab6eb50f1591ccc0ad29780 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:20:53 +0000 Subject: [PATCH 133/293] Implemented displaying the download speed and estimated finish time. Looks and behaves the same as in Tracker's status window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@352 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 251 ++++++++++++++++-- src/apps/webpositive/DownloadProgressView.h | 27 +- src/apps/webpositive/DownloadWindow.cpp | 15 +- 3 files changed, 273 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index bedbc67bad..5284fb2e31 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -35,15 +35,17 @@ #include #include #include -#include +#include #include #include #include #include #include +#include #include "WebDownload.h" #include "WebPage.h" +#include "StringForSize.h" enum { @@ -53,6 +55,14 @@ enum { REMOVE_DOWNLOAD = 'rmdn', }; +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: @@ -167,22 +177,20 @@ public: DownloadProgressView::DownloadProgressView(BWebDownload* download) : - BGridView(8, 3), + BGroupView(B_HORIZONTAL, 8), fDownload(download), fURL(download->URL()), - fPath(download->Path()), - fExpectedSize(download->ExpectedSize()) + fPath(download->Path()) { } DownloadProgressView::DownloadProgressView(const BMessage* archive) : - BGridView(8, 3), + BGroupView(B_HORIZONTAL, 8), fDownload(NULL), fURL(), - fPath(), - fExpectedSize(0) + fPath() { const char* string; if (archive->FindString("path", &string) == B_OK) @@ -195,10 +203,22 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) 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); - BGridLayout* layout = GridLayout(); if (archive) { fStatusBar = new BStatusBar("download progress", fPath.Leaf()); float value; @@ -233,11 +253,37 @@ DownloadProgressView::Init(BMessage* archive) fBottomButton->SetEnabled(fDownload == NULL); } + fInfoView = new BStringView("info view", ""); + + BGroupLayout* layout = GroupLayout(); layout->SetInsets(8, 5, 5, 6); - layout->AddView(fIconView, 0, 0, 1, 2); - layout->AddView(fStatusBar, 1, 0, 1, 2); - layout->AddView(fTopButton, 2, 0); - layout->AddView(fBottomButton, 2, 1); + layout->AddView(fIconView); + BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) + .Add(fStatusBar) + .Add(fInfoView) + ; + verticalGroup->SetViewColor(ViewColor()); + layout->AddView(verticalGroup); + verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) + .Add(fTopButton) + .Add(fBottomButton) + ; + 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)); +// font_height fontHeight; +// font.GetHeight(&fontHeight); +// float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); +// fInfoView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); +// fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, textHeight)); + fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); return true; } @@ -314,13 +360,23 @@ DownloadProgressView::MessageReceived(BMessage* message) 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: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - fStatusBar->SetTo(progress); + int64 currentSize; + int64 expectedSize; + if (message->FindInt64("current size", ¤tSize) == B_OK + && message->FindInt64("expected size", &expectedSize) == B_OK) { + _UpdateStatus(currentSize, expectedSize); + } break; } case OPEN_DOWNLOAD: @@ -427,7 +483,7 @@ DownloadProgressView::MessageReceived(BMessage* message) break; } default: - BGridView::MessageReceived(message); + BGroupView::MessageReceived(message); } } @@ -468,6 +524,7 @@ DownloadProgressView::DownloadFinished() fBottomButton->SetLabel("Remove"); fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); + fInfoView->SetText(""); } @@ -484,9 +541,171 @@ DownloadProgressView::DownloadCanceled() } +/*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 = "("; + buffer << string_for_size((double)fCurrentSize, sizeBuffer, + sizeof(sizeBuffer)); + buffer << " of "; + buffer << string_for_size((double)fExpectedSize, sizeBuffer, + sizeof(sizeBuffer)); + 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) { diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index d39ca93380..4c4ae7e48f 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -28,12 +28,13 @@ #define DOWNLOAD_PROGRESS_VIEW_H -#include +#include #include #include class BEntry; class BStatusBar; +class BStringView; class BWebDownload; class IconView; class SmallButton; @@ -44,7 +45,7 @@ enum { }; -class DownloadProgressView : public BGridView { +class DownloadProgressView : public BGroupView { public: DownloadProgressView(BWebDownload* download); DownloadProgressView(const BMessage* archive); @@ -68,19 +69,41 @@ public: 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 diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index a2f3f38aff..5f6dbf1867 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ public: : BGroupView(B_VERTICAL) { + SetFlags(Flags() | B_PULSE_NEEDED); SetViewColor(245, 245, 245); AddChild(BSpaceLayoutItem::CreateGlue()); } @@ -75,6 +77,11 @@ public: return BSize(minSize.width, 80); } + virtual void Pulse() + { + DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse(); + } + protected: virtual void DoLayout() { @@ -129,6 +136,8 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { + SetPulseRate(1000000); + settings->AddListener(BMessenger(this)); BPath downloadPath; if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) @@ -159,15 +168,17 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, new BMessage(REMOVE_MISSING_DOWNLOADS)); fRemoveMissingButton->SetEnabled(false); + const float spacing = be_control_look->DefaultItemSpacing(); + AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) .Add(scrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .AddGlue() .Add(fRemoveMissingButton) .Add(fRemoveFinishedButton) - .SetInsets(5, 5, 5, 5) + .SetInsets(12, 5, 12, 5) ) ); From 3b7f919fb80f5f90a2be6f11a7602f49cad7242e Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:21:24 +0000 Subject: [PATCH 134/293] Removed commented out code which wasn't needed after all. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@353 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 5284fb2e31..8d780ac695 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -278,11 +278,6 @@ DownloadProgressView::Init(BMessage* archive) fInfoView->SetFont(&font, B_FONT_SIZE); fInfoView->SetHighColor(tint_color(fInfoView->LowColor(), B_DARKEN_4_TINT)); -// font_height fontHeight; -// font.GetHeight(&fontHeight); -// float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); -// fInfoView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); -// fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, textHeight)); fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); return true; From c5d7a6c9490b6ed384171e082b032c52f7cb63b7 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:25:54 +0000 Subject: [PATCH 135/293] Manually removing downloads needs to trigger checking the button enabled status in the download window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@354 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 22 ++++++++++++++++++++++ src/apps/webpositive/DownloadWindow.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 5f6dbf1867..71ba1a3894 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -250,6 +250,7 @@ DownloadWindow::MessageReceived(BMessage* message) _RemoveMissingDownloads(); break; case SAVE_SETTINGS: + _ValidateButtonStatus(); _SaveSettings(); break; @@ -390,6 +391,27 @@ DownloadWindow::_RemoveMissingDownloads() } +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( + item->View()); + if (!view) + continue; + if (view->IsFinished()) + finishedCount++; + if (view->IsMissing()) + missingCount++; + } + fRemoveFinishedButton->SetEnabled(finishedCount > 0); + fRemoveMissingButton->SetEnabled(missingCount > 0); +} + + void DownloadWindow::_SaveSettings() { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 3275620293..02f950b86b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -52,6 +52,7 @@ private: void _DownloadFinished(BWebDownload* download); void _RemoveFinishedDownloads(); void _RemoveMissingDownloads(); + void _ValidateButtonStatus(); void _SaveSettings(); void _LoadSettings(); bool _OpenSettingsFile(BFile& file, uint32 mode); From 2232d801e0b2fc09f38a573e562295c64a842239 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:27:26 +0000 Subject: [PATCH 136/293] Canceling a download needs to unset the info text. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@355 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 8d780ac695..7ae7dc04e8 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -533,6 +533,7 @@ DownloadProgressView::DownloadCanceled() fBottomButton->SetLabel("Remove"); fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); + fInfoView->SetText(""); } From 98b056e146c200b0cff22904ea2f6b4dae94f8db Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 22:30:20 +0000 Subject: [PATCH 137/293] * Scroll the downloads which just started into view. * Delete the progress view when init fails. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@356 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 27 +++++++++++++++++++++---- src/apps/webpositive/DownloadWindow.h | 2 ++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 71ba1a3894..1a318338a1 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -157,8 +157,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); - BScrollView* scrollView = new DownloadContainerScrollView( - downloadsGroupView); + fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); fRemoveFinishedButton = new BButton("Remove finished", new BMessage(REMOVE_FINISHED_DOWNLOADS)); @@ -172,7 +171,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) - .Add(scrollView) + .Add(fDownloadsScrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .AddGlue() @@ -280,6 +279,9 @@ DownloadWindow::QuitRequested() } +// #pragma mark - private + + void DownloadWindow::_DownloadStarted(BWebDownload* download) { @@ -308,9 +310,26 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) fRemoveFinishedButton->SetEnabled(finishedCount > 0); fRemoveMissingButton->SetEnabled(missingCount > 0); DownloadProgressView* view = new DownloadProgressView(download); - if (!view->Init()) + if (!view->Init()) { + delete view; return; + } fDownloadViewsLayout->AddView(index, view); + float viewHeight = view->MinSize().height + 1; + if (BScrollBar* scrollBar = fDownloadsScrollView->ScrollBar(B_VERTICAL)) { + float min; + float max; + scrollBar->GetRange(&min, &max); + 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); diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 02f950b86b..92d299c89b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,6 +34,7 @@ class BButton; class BFile; class BGroupLayout; +class BScrollView; class BWebDownload; class SettingsMessage; @@ -58,6 +59,7 @@ private: bool _OpenSettingsFile(BFile& file, uint32 mode); private: + BScrollView* fDownloadsScrollView; BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; BButton* fRemoveMissingButton; From ec7e3b29c40b13246d3cbc916689da2c533ed0d9 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 22:32:04 +0000 Subject: [PATCH 138/293] Move variable declaration into proper scope and where it's first needed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@357 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 1a318338a1..225b3e931c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -315,11 +315,13 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) return; } fDownloadViewsLayout->AddView(index, view); - float viewHeight = view->MinSize().height + 1; + + // 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(); @@ -330,6 +332,7 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) scrollBar->SetValue(value + diff); } } + _SaveSettings(); SetWorkspaces(B_CURRENT_WORKSPACE); From 5d164e55a582358fe0740e12dd6943d04d515164 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Mar 2010 11:32:14 +0000 Subject: [PATCH 139/293] Use a better algorithm to figure out the final favicon display size. Icons which can be scaled down by an even factor will now be displayed better. Also enable smooth scaling and use a better drawing mode. The net result is that icons will be displayed between 14x14 and 18x18 with the best suitable scaling factor. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@358 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 9f40c9aeef..997d359bad 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -874,11 +874,28 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, // 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_OVER); - owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); + 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; } From bef126e25eeb544adb3a3af89facb0bd481b9383 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 13:40:04 +0000 Subject: [PATCH 140/293] white space cleanup. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@360 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0c60ca1f91..c2f0173470 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1224,7 +1224,7 @@ BrowserWindow::_ShowBookmarks() status = get_ref_for_path(path.Path(), &ref); if (status == B_OK) status = be_roster->Launch(&ref); - + if (status != B_OK && status != B_ALREADY_RUNNING) { BString message("There was an error trying to show the Bookmarks " "folder.\n\n"); From 5a9074bc173ee55df43495bf0581542b38eec2e8 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 13:48:17 +0000 Subject: [PATCH 141/293] * Added static method BWebPage::ShutdownOnce(), which the application can call for any at-exit-cleanup. Moved the closing of the favicon database from BWebSettings there, since I wasn't sure if closing the icon database happened at the right time, or perhaps too late if it was done via global destructors. * Temporarily disabled the native cookie support, as it only delays application startup time right now. We are really using the cURL cookies at the moment and they work just fine it seems. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@362 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index db118555b5..756970e686 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -54,6 +54,9 @@ 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), @@ -62,6 +65,7 @@ BrowserApp::BrowserApp() fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), + fCookies(NULL), fCookieJar(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) @@ -129,6 +133,7 @@ BrowserApp::ReadyToRun() 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, @@ -137,6 +142,7 @@ BrowserApp::ReadyToRun() cookieArchive = fCookies->GetValue("cookies", cookieArchive); fCookieJar = new BNetworkCookieJar(cookieArchive); BWebPage::SetCookieJar(fCookieJar); +#endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", @@ -265,6 +271,8 @@ BrowserApp::QuitRequested() } } + BWebPage::ShutdownOnce(); + fSettings->SetValue("window frame", fLastWindowFrame); if (fDownloadWindow->Lock()) { fSettings->SetValue("downloads window frame", fDownloadWindow->Frame()); @@ -277,7 +285,7 @@ BrowserApp::QuitRequested() } BMessage cookieArchive; - if (fCookieJar->Archive(&cookieArchive) == B_OK) + if (fCookieJar != NULL && fCookieJar->Archive(&cookieArchive) == B_OK) fCookies->SetValue("cookies", cookieArchive); return true; From 979c4b319ddb3362910b9cd3e197ee561da148f7 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 21:16:25 +0000 Subject: [PATCH 142/293] Replace the previous resize request implementation by a more advanced one: * Ignore resize requests when the window has more than one tab at all. * Make sure the new size is not larger than the screen and shift the window so everything is visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@368 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 36 +++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c2f0173470..b797a9c57e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -953,8 +954,41 @@ BrowserWindow::ResizeRequested(float width, float height, BWebView* view) if (view != CurrentWebView()) return; - // TODO: Ignore request when there is more than one BWebView embedded! + // Ignore request when there is more than one BWebView embedded. + if (fTabManager->CountTabs() > 1) + return; + // Make sure the new frame is not larger than the screen frame minus + // window decorator border. + BScreen screen(this); + BRect screenFrame = screen.Frame(); + BRect decoratorFrame = DecoratorFrame(); + BRect frame = Frame(); + + screenFrame.left += decoratorFrame.left - frame.left; + screenFrame.right += decoratorFrame.right - frame.right; + screenFrame.top += decoratorFrame.top - frame.top; + screenFrame.bottom += decoratorFrame.bottom - frame.bottom; + + width = min_c(width, screen.Frame().Width()); + height = min_c(height, screen.Frame().Height()); + + frame.right = frame.left + width; + frame.bottom = frame.top + height; + + // frame is now not larger than screenFrame, but may still be partly outside + if (!screenFrame.Contains(frame)) { + if (frame.left < screenFrame.left) + frame.OffsetBy(screenFrame.left - frame.left, 0); + else if (frame.right > screenFrame.right) + frame.OffsetBy(screenFrame.right - frame.right, 0); + if (frame.top < screenFrame.top) + frame.OffsetBy(screenFrame.top - frame.top, 0); + else if (frame.bottom > screenFrame.bottom) + frame.OffsetBy(screenFrame.bottom - frame.bottom, 0); + } + + MoveTo(frame.left, frame.top); ResizeTo(width, height); } From f41f9676685fd60ab63167aec3d128c44b596494 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 12:45:22 +0000 Subject: [PATCH 143/293] Made method that returns the tab index for a contained view public. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@377 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 29 +++++++++++++++-------------- src/apps/webpositive/WebTabView.h | 5 +---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 997d359bad..d953d2ee99 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1318,6 +1318,19 @@ TabManager::ViewForTab(int32 tabIndex) const } +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; +} + + void TabManager::SelectTab(int32 tabIndex) { @@ -1333,7 +1346,7 @@ TabManager::SelectTab(int32 tabIndex) void TabManager::SelectTab(const BView* containedView) { - int32 tabIndex = _TabIndexForContainedView(containedView); + int32 tabIndex = TabForView(containedView); if (tabIndex > 0) SelectTab(tabIndex); } @@ -1401,7 +1414,7 @@ void TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) { WebTabView* tab = dynamic_cast(fTabContainerView->TabAt( - _TabIndexForContainedView(containedView))); + TabForView(containedView))); if (tab) tab->SetIcon(icon); } @@ -1417,15 +1430,3 @@ TabManager::SetCloseButtonsAvailable(bool available) } -int32 -TabManager::_TabIndexForContainedView(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; -} - diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 93129b1b0c..23ea4cc62f 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -60,6 +60,7 @@ public: BView* ContainerView() const; BView* ViewForTab(int32 tabIndex) const; + int32 TabForView(const BView* containedView) const; void SelectTab(int32 tabIndex); void SelectTab(const BView* containedView); @@ -76,10 +77,6 @@ public: const BBitmap* icon); void SetCloseButtonsAvailable(bool available); -private: - int32 _TabIndexForContainedView( - const BView* containedView) const; - private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; From ea8b6f3fd1eb3234a2c8b862276ee6104671fbd9 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 12:47:12 +0000 Subject: [PATCH 144/293] * Reworked closing a page programatically. BWebPage no longer sends a plain B_QUIT_REQUESTED, instead BWebWindow has a new hook and derived classes can implement it. * Some refactoring in BrowserWindow to move code from MessageReceived into separate methods for easier debugging and cleaner code. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@378 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 51 ++++++++++++++++++-------- src/apps/webpositive/BrowserWindow.h | 2 + 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b797a9c57e..8f7347ed18 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -650,20 +650,7 @@ printf(" file ok\n"); int32 index; if (message->FindInt32("tab index", &index) != B_OK) index = -1; - BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - break; - SetCurrentWebView(webView); - if (webView) - _UpdateTitle(webView->MainFrameTitle()); - else - _UpdateTitle(""); - if (webView) { - fURLTextControl->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } + _TabChanged(index); break; } @@ -876,6 +863,20 @@ BrowserWindow::NewPageCreated(BWebView* view) } +void +BrowserWindow::CloseWindowRequested(BWebView* view) +{ + int32 index = fTabManager->TabForView(view); + if (index < 0) { + // Tab is already gone. + return; + } + BMessage message(CLOSE_TAB); + message.AddInt32("tab index", index); + PostMessage(&message, this); +} + + void BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { @@ -1122,7 +1123,7 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - //fTabGroup->SetVisible(fTabManager->CountTabs() > 1); +// fTabGroup->SetVisible(fTabManager->CountTabs() > 1); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } @@ -1141,6 +1142,26 @@ BrowserWindow::_ShutdownTab(int32 index) } +void +BrowserWindow::_TabChanged(int32 index) +{ + BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + return; + SetCurrentWebView(webView); + if (webView) + _UpdateTitle(webView->MainFrameTitle()); + else + _UpdateTitle(""); + if (webView) { + fURLTextControl->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } +} + + status_t BrowserWindow::_BookmarkPath(BPath& path) const { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4e6cac811c..823db49adb 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -87,6 +87,7 @@ private: BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); + virtual void CloseWindowRequested(BWebView* view); virtual void NewPageCreated(BWebView* view); virtual void LoadNegotiating(const BString& url, BWebView* view); @@ -121,6 +122,7 @@ private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); void _ShutdownTab(int32 index); + void _TabChanged(int32 index); status_t _BookmarkPath(BPath& path) const; void _CreateBookmark(); From 062b23723784dd9e91828e8a7bcf59b7518f81cb Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 16:46:54 +0000 Subject: [PATCH 145/293] * Added optional BWebView parameter passed to BrowserWindow constructor, which will be passed to CreateNewTab(), so that BrowserWindows can be created to embed a view which already exists. * Extended NewPageCreated() hook with the additional information that BWebPage::createPage() already provides. It can be used to decide if new windows shall be created instead of creating another tab for the new page. * Reworked BrowserWindow constructor with regards to the "DoNotHaveToolbar" policy. All views are always created, BLayoutItems are remembered for the various groups and are being turned invisible depending on policy. This way each BrowserWindow is fully valid and can be reconfigured easily during runtime. (Settings could be exposed as well now.) * Changed ChromeClientHaiku::createWindow() implementation to not disregard the "window features" properties if only some of them are not set. All this combined makes the Haiku User Guide translation page open a separate window for editing the translations just like BeZillaBrowser. What does not work (but apparently also not in BeZillaBrowser) is clicking another block and having the editing window update to show that block instead. Don't know if this is actually supposed to work that way, it just seems like it should. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@380 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 306 +++++++++++++------------ src/apps/webpositive/BrowserWindow.h | 14 +- 2 files changed, 169 insertions(+), 151 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8f7347ed18..07a5f62087 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -238,7 +238,8 @@ public: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) +BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, + BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, @@ -250,162 +251,165 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) newTabMessage->AddBool("select", true); fTabManager = new TabManager(BMessenger(this), newTabMessage); - if (toolbarPolicy == HaveToolbar) { - // Menu + // Menu #if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* mainMenu = fTabManager->Menu(); + BMenu* mainMenu = fTabManager->Menu(); #else - BMenu* mainMenu = new BMenuBar("Main menu"); + BMenu* mainMenu = new BMenuBar("Main menu"); #endif - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - mainMenu->AddItem(menu); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + mainMenu->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - mainMenu->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + mainMenu->AddItem(menu); - fGoMenu = new BMenu("Go"); - mainMenu->AddItem(fGoMenu); + fGoMenu = new BMenu("Go"); + mainMenu->AddItem(fGoMenu); - BPath bookmarkPath; - entry_ref bookmarkRef; - if (_BookmarkPath(bookmarkPath) == B_OK - && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { - BMenu* bookmarkMenu - = new BookmarkMenu("Bookmarks", this, &bookmarkRef); - mainMenu->AddItem(bookmarkMenu); - } - - // Back, Forward & Stop - fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); - fBackButton->SetIcon(201); - fBackButton->TrimIcon(); - - fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); - fForwardButton->SetIcon(202); - fForwardButton->TrimIcon(); - - fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); - fStopButton->SetIcon(204); - fStopButton->TrimIcon(); - - // URL - fURLTextControl = new BTextControl("url", "", "", NULL); - fURLTextControl->SetDivider(50.0); - - // Go - fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); - - // Status Bar - fStatusText = new BStringView("status", ""); - fStatusText->SetAlignment(B_ALIGN_LEFT); - fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - fStatusText->SetExplicitMinSize(BSize(150, 12)); - // Prevent the window from growing to fit a long status message... - BFont font(be_plain_font); - font.SetSize(ceilf(font.Size() * 0.8)); - fStatusText->SetFont(&font, B_FONT_SIZE); - - // Loading progress bar - fLoadingProgressBar = new BStatusBar("progress"); - fLoadingProgressBar->SetMaxValue(100); - fLoadingProgressBar->Hide(); - fLoadingProgressBar->SetBarHeight(12); - - const float kInsetSpacing = 3; - const float kElementSpacing = 5; - - fFindTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); - fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) - .Add(fFindCaseSensitiveCheckBox) - .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) - .SetInsets(kInsetSpacing, kInsetSpacing, - kInsetSpacing, kInsetSpacing) - ) - ; - // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) -#if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(mainMenu) -#endif - .Add(fTabManager->TabGroup()) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(fBackButton, 0, 0) - .Add(fForwardButton, 1, 0) - .Add(fStopButton, 2, 0) - .Add(fURLTextControl, 3, 0) - .Add(fGoButton, 4, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(fTabManager->ContainerView()) - .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fStatusText) - .Add(fLoadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) - ) - ); - - fURLTextControl->MakeFocus(true); - - fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel()); - - fFindGroup = layoutItemFor(findGroup); - fTabGroup = layoutItemFor(fTabManager->TabGroup()); - } else { - fBackButton = 0; - fForwardButton = 0; - fStopButton = 0; - fGoButton = 0; - fURLTextControl = 0; - fURLAutoCompleter = 0; - fStatusText = 0; - fLoadingProgressBar = 0; - - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(fTabManager->ContainerView()) - ); + BPath bookmarkPath; + entry_ref bookmarkRef; + if (_BookmarkPath(bookmarkPath) == B_OK + && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { + BMenu* bookmarkMenu + = new BookmarkMenu("Bookmarks", this, &bookmarkRef); + mainMenu->AddItem(bookmarkMenu); } - CreateNewTab("", true); + // Back, Forward & Stop + fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + fBackButton->SetIcon(201); + fBackButton->TrimIcon(); + + fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + fForwardButton->SetIcon(202); + fForwardButton->TrimIcon(); + + fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + fStopButton->SetIcon(204); + fStopButton->TrimIcon(); + + // URL + fURLTextControl = new BTextControl("url", "", "", NULL); + fURLTextControl->SetDivider(50.0); + + // Go + fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); + + // Status Bar + fStatusText = new BStringView("status", ""); + fStatusText->SetAlignment(B_ALIGN_LEFT); + fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + fStatusText->SetExplicitMinSize(BSize(150, 12)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + fStatusText->SetFont(&font, B_FONT_SIZE); + + // Loading progress bar + fLoadingProgressBar = new BStatusBar("progress"); + fLoadingProgressBar->SetMaxValue(100); + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetBarHeight(12); + + const float kInsetSpacing = 3; + const float kElementSpacing = 5; + + fFindTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fFindTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(fFindCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + + BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(fBackButton, 0, 0) + .Add(fForwardButton, 1, 0) + .Add(fStopButton, 2, 0) + .Add(fURLTextControl, 3, 0) + .Add(fGoButton, 4, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + ; + + BView* statusGroup = BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ; + + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) +#if !INTEGRATE_MENU_INTO_TAB_BAR + .Add(mainMenu) +#endif + .Add(fTabManager->TabGroup()) + .Add(navigationGroup) + .Add(fTabManager->ContainerView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(statusGroup) + ); + + fURLTextControl->MakeFocus(true); + + fURLAutoCompleter = new TextControlCompleter(fURLTextControl, + new BrowsingHistoryChoiceModel()); + + fMenuGroup = layoutItemFor(mainMenu); + fTabGroup = layoutItemFor(fTabManager->TabGroup()); + fNavigationGroup = layoutItemFor(navigationGroup); + fFindGroup = layoutItemFor(findGroup); + fStatusGroup = layoutItemFor(statusGroup); + + CreateNewTab("", true, webView); fFindGroup->SetVisible(false); + if (toolbarPolicy == DoNotHaveToolbar) { +#if !INTEGRATE_MENU_INTO_TAB_BAR + fMenuGroup->SetVisible(false); +#endif + fTabGroup->SetVisible(false); + fNavigationGroup->SetVisible(false); + } + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); @@ -857,9 +861,15 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) void -BrowserWindow::NewPageCreated(BWebView* view) +BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, + bool modalDialog, bool resizable) { - CreateNewTab(BString(), true, view); + if (windowFrame.IsValid()) { + BrowserWindow* window = new BrowserWindow(windowFrame, + DoNotHaveToolbar, view); + window->Show(); + } else + CreateNewTab(BString(), true, view); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 823db49adb..9d552f9b4d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -69,7 +69,8 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, - ToolbarPolicy = HaveToolbar); + ToolbarPolicy = HaveToolbar, + BWebView* webView = NULL); virtual ~BrowserWindow(); virtual void DispatchMessage(BMessage* message, @@ -88,7 +89,9 @@ private: virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void CloseWindowRequested(BWebView* view); - virtual void NewPageCreated(BWebView* view); + virtual void NewPageCreated(BWebView* view, + BRect windowFrame, bool modalDialog, + bool resizable); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, @@ -147,8 +150,13 @@ private: TextControlCompleter* fURLAutoCompleter; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; - BLayoutItem* fFindGroup; + + BLayoutItem* fMenuGroup; BLayoutItem* fTabGroup; + BLayoutItem* fNavigationGroup; + BLayoutItem* fFindGroup; + BLayoutItem* fStatusGroup; + BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; From 92e8b344ace812f44309a3d8afd5e8572cc2a147 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 19:32:47 +0000 Subject: [PATCH 146/293] Added option and infrastructure to zoom the whole page instead of the text only. (Currently not remembered, but the default (off) is often better than zooming images.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@381 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 38 +++++++++++++++++--------- src/apps/webpositive/BrowserWindow.h | 3 ++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 07a5f62087..399c258611 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -82,9 +82,10 @@ enum { CREATE_BOOKMARK = 'crbm', SHOW_BOOKMARKS = 'shbm', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', @@ -243,7 +244,8 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fZoomTextOnly(true) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -282,9 +284,13 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, menu = new BMenu("Text"); menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(ZOOM_FACTOR_RESET), '0')); + fZoomTextOnlyMenuItem = new BMenuItem("Zoom text only", + new BMessage(ZOOM_TEXT_ONLY)); + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + menu->AddItem(fZoomTextOnlyMenuItem); mainMenu->AddItem(menu); fGoMenu = new BMenu("Go"); @@ -593,14 +599,20 @@ printf(" file ok\n"); break; } - case TEXT_SIZE_INCREASE: - CurrentWebView()->IncreaseTextSize(); + case ZOOM_FACTOR_INCREASE: + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); break; - case TEXT_SIZE_DECREASE: - CurrentWebView()->DecreaseTextSize(); + case ZOOM_FACTOR_DECREASE: + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); break; - case TEXT_SIZE_RESET: - CurrentWebView()->ResetTextSize(); + case ZOOM_FACTOR_RESET: + CurrentWebView()->ResetZoomFactor(); + break; + case ZOOM_TEXT_ONLY: + fZoomTextOnly = !fZoomTextOnly; + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + // TODO: Would be nice to have an instant update if the page is already + // zoomed. break; case TEXT_FIND_NEXT: diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9d552f9b4d..e1ec942b2e 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -40,6 +40,7 @@ class BDirectory; class BFile; class BLayoutItem; class BMenu; +class BMenuItem; class BPath; class BStatusBar; class BStringView; @@ -142,6 +143,8 @@ private: private: BMenu* fGoMenu; + BMenuItem* fZoomTextOnlyMenuItem; + bool fZoomTextOnly; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From cb0b497952438ca8ddd066ae673d8692e66864e7 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 19:49:12 +0000 Subject: [PATCH 147/293] Don't display the unit of the current size if it's the same as the unit of the expected size in the download progress view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@382 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 7ae7dc04e8..ddee6317c5 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -110,7 +110,7 @@ public: Invalidate(); } } - + bool IsIconDimmed() const { return fDimmedIcon; @@ -307,7 +307,7 @@ DownloadProgressView::AttachedToWindow() fDownload->SetProgressListener(BMessenger(this)); fTopButton->SetTarget(this); fBottomButton->SetTarget(this); - + BEntry entry(fPath.Path()); if (entry.Exists()) _StartNodeMonitor(entry); @@ -604,11 +604,23 @@ DownloadProgressView::_UpdateStatusText() // Draw speed info char sizeBuffer[128]; buffer = "("; - buffer << string_for_size((double)fCurrentSize, sizeBuffer, + // 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 << string_for_size((double)fExpectedSize, sizeBuffer, - sizeof(sizeBuffer)); + buffer << expectedSize; buffer << ", "; buffer << string_for_size(fBytesPerSecond, sizeBuffer, sizeof(sizeBuffer)); From 65e61cdca4cce6bcc491608fb4971cb55ea37aa8 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 5 Apr 2010 17:05:17 +0000 Subject: [PATCH 148/293] * Make use of the new svn revision jam magic to embed the current svn version into the about window. * Give access to the about window from the browser windows. * Renamed the "Show *" entries in the Window menu to just "*". git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@387 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 9 ++++++--- src/apps/webpositive/BrowserWindow.cpp | 7 +++++-- src/apps/webpositive/svn_revision.cpp | 10 ++++++++++ src/apps/webpositive/svn_revision.h | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/apps/webpositive/svn_revision.cpp create mode 100644 src/apps/webpositive/svn_revision.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 756970e686..29439d2fde 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -34,6 +34,7 @@ #include "DownloadWindow.h" #include "SettingsMessage.h" #include "SettingsWindow.h" +#include "svn_revision.h" #include "NetworkCookieJar.h" #include "WebPage.h" #include "WebSettings.h" @@ -86,9 +87,11 @@ BrowserApp::~BrowserApp() void BrowserApp::AboutRequested() { - BAlert* alert = new BAlert("About WebPositive", - "WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " - "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus", + BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " + "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus"); + aboutText << "\n\nSVN revision: " << kSVNRevision; + + BAlert* alert = new BAlert("About WebPositive", aboutText.String(), "Sweet!"); alert->Go(); } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 399c258611..4b7cdc8c4e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -273,8 +273,11 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); + menu->AddItem(new BMenuItem("Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Settings", new BMessage(SHOW_SETTINGS_WINDOW))); + BMenuItem* aboutItem = new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED)); + menu->AddItem(aboutItem); + aboutItem->SetTarget(be_app); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); diff --git a/src/apps/webpositive/svn_revision.cpp b/src/apps/webpositive/svn_revision.cpp new file mode 100644 index 0000000000..489c64cdd4 --- /dev/null +++ b/src/apps/webpositive/svn_revision.cpp @@ -0,0 +1,10 @@ +/* + * Copyright 2006-2009, Ingo Weinhold + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "svn_revision.h" + +const int32 kSVNRevision = + #include "svn_revision" +; diff --git a/src/apps/webpositive/svn_revision.h b/src/apps/webpositive/svn_revision.h new file mode 100644 index 0000000000..fff9e9b122 --- /dev/null +++ b/src/apps/webpositive/svn_revision.h @@ -0,0 +1,15 @@ +/* + * Copyright 2006-2009, Ingo Weinhold + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef SVN_REVISION_H +#define SVN_REVISION_H + +#include + + +extern const int32 kSVNRevision; + + +#endif // SVN_REVISION_H From 0145cf4349fcd01b8daa93c46703d7a03c4c0a47 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 01:24:07 +0000 Subject: [PATCH 149/293] Remember the currently focused view within a tab in the user data that can be associated with a BWebView and restore the focus when the tab changes. This fixes a number of annoying issues. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@391 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b7cdc8c4e..5f96f7fa5c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -236,6 +236,24 @@ public: }; +class PageUserData : public BWebView::UserData { +public: + PageUserData(BView* focusedView) + : + fFocusedView(focusedView) + { + } + + BView* FocusedView() const + { + return fFocusedView; + } + +private: + BView* fFocusedView; +}; + + // #pragma mark - BrowserWindow @@ -1173,7 +1191,17 @@ BrowserWindow::_TabChanged(int32 index) BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); if (webView == CurrentWebView()) return; + + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + SetCurrentWebView(webView); + + PageUserData* userData = static_cast(webView->GetUserData()); + if (userData) + userData->FocusedView()->MakeFocus(true); + else + webView->MakeFocus(true); + if (webView) _UpdateTitle(webView->MainFrameTitle()); else From bb68c7f66d8d4f445bec5fd4928f5d92cdb25e54 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:50:17 +0000 Subject: [PATCH 150/293] White space cleanup git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@392 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/SettingsMessage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index bf2822dd8e..8f22785788 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -29,7 +29,7 @@ public: SettingsMessage(directory_which directory, const char* filename); virtual ~SettingsMessage(); - + status_t InitCheck() const; status_t Load(); From d5f0e82b842da208d3c297fa2c5eb22ad75539cf Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:52:43 +0000 Subject: [PATCH 151/293] * Moved some settings keys into new files SettingsKeys.h/cpp to make it less likely to introduce erros with spelling settings keys wrong somewhere. * Introduced new setting for the behavior if tabs should show at all if only one page is showing in a window. Defaults to on, i.e. the previous behavior. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@393 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 4 +- src/apps/webpositive/BrowserWindow.cpp | 402 +++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 9 +- src/apps/webpositive/SettingsKeys.cpp | 32 ++ src/apps/webpositive/SettingsKeys.h | 37 +++ src/apps/webpositive/SettingsWindow.cpp | 77 +++-- src/apps/webpositive/SettingsWindow.h | 2 + 7 files changed, 347 insertions(+), 216 deletions(-) create mode 100644 src/apps/webpositive/SettingsKeys.cpp create mode 100644 src/apps/webpositive/SettingsKeys.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 29439d2fde..1cade8cd09 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -167,7 +167,7 @@ BrowserApp::ReadyToRun() delete fLaunchRefsMessage; fLaunchRefsMessage = 0; } else { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -327,7 +327,7 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); if (url.Length()) window->CurrentWebView()->LoadURL(url.String()); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5f96f7fa5c..a5d8fa2671 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -38,6 +38,8 @@ #include "BrowsingHistory.h" #include "IconButton.h" #include "NavMenu.h" +#include "SettingsKeys.h" +#include "SettingsMessage.h" #include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" @@ -257,14 +259,21 @@ private: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, - BWebView* webView) +BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, + ToolbarPolicy toolbarPolicy, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), - fZoomTextOnly(true) + fAppSettings(appSettings), + fZoomTextOnly(true), + fShowTabsIfSinglePageOpen(true) { + fAppSettings->AddListener(BMessenger(this)); +// fZoomTextOnly = fAppSettings->GetValue("zoom text only", fZoomTextOnly); + fShowTabsIfSinglePageOpen = fAppSettings->GetValue( + kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); @@ -461,6 +470,7 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, BrowserWindow::~BrowserWindow() { + fAppSettings->RemoveListener(BMessenger(this)); delete fURLAutoCompleter; delete fTabManager; } @@ -501,199 +511,220 @@ void BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { - case OPEN_LOCATION: - if (fURLTextControl) { - if (fURLTextControl->TextView()->IsFocus()) - fURLTextControl->TextView()->SelectAll(); - else - fURLTextControl->MakeFocus(true); - } - break; - case RELOAD: - CurrentWebView()->Reload(); - break; - case GOTO_URL: { - BString url; - if (message->FindString("url", &url) != B_OK) - url = fURLTextControl->Text(); - fTabManager->SetTabIcon(CurrentWebView(), NULL); - CurrentWebView()->LoadURL(url.String()); - break; - } - case GO_BACK: - CurrentWebView()->GoBack(); - break; - case GO_FORWARD: - CurrentWebView()->GoForward(); - break; - case STOP: - CurrentWebView()->StopLoading(); - break; - - case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::DefaultInstance(); - if (history->CountItems() == 0) + case OPEN_LOCATION: + if (fURLTextControl) { + if (fURLTextControl->TextView()->IsFocus()) + fURLTextControl->TextView()->SelectAll(); + else + fURLTextControl->MakeFocus(true); + } + break; + case RELOAD: + CurrentWebView()->Reload(); + break; + case GOTO_URL: + { + BString url; + if (message->FindString("url", &url) != B_OK) + url = fURLTextControl->Text(); + fTabManager->SetTabIcon(CurrentWebView(), NULL); + CurrentWebView()->LoadURL(url.String()); break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to " - "clear the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->Clear(); - break; - } - - case CREATE_BOOKMARK: - _CreateBookmark(); - break; - case SHOW_BOOKMARKS: - _ShowBookmarks(); - break; - - case B_REFS_RECEIVED: { - // Currently the only source of these messages is the bookmarks menu. - // Filter refs into URLs, this also gets rid of refs for folders. - // For clicks on sub-folders in the bookmarks menu, we have Tracker - // open the corresponding folder. - entry_ref ref; - uint32 addedCount = 0; - for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { -printf("B_REFS_RECEIVED: %s\n", ref.name); - BEntry entry(&ref); - uint32 addedSubCount = 0; - if (entry.IsDirectory()) { - BDirectory directory(&entry); -printf(" directory ok\n"); - _AddBookmarkURLsRecursively(directory, message, addedSubCount); - } else { - BFile file(&ref, B_READ_ONLY); -printf(" file ok\n"); - BString url; - if (_ReadURLAttr(file, url)) { - message->AddString("url", url.String()); - addedSubCount++; - } - } - if (addedSubCount == 0) { - // Don't know what to do with this entry, just pass it - // on to the system to handle. Note that this may result - // in us opening other supported files via the application - // mechanism. - be_roster->Launch(&ref); - } - addedCount += addedSubCount; } - message->RemoveName("refs"); - if (addedCount > 10) { - BString string; - string << "Do you want to open " << addedCount; - string << " bookmarks all at once?"; - BAlert* alert = new BAlert("Open bookmarks confirmation", - string.String(), "Cancel", "Open all"); - if (alert->Go() == 0) + case GO_BACK: + CurrentWebView()->GoBack(); + break; + case GO_FORWARD: + CurrentWebView()->GoForward(); + break; + case STOP: + CurrentWebView()->StopLoading(); + break; + + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (history->CountItems() == 0) break; - } - be_app->PostMessage(message); - break; - } - case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. - type_code type; - int32 countFound; - if (message->GetInfo("refs", &type, &countFound) != B_OK - || type != B_REF_TYPE) { + BAlert* alert = new BAlert("Confirmation", "Do you really want to " + "clear the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->Clear(); break; } - if (countFound > 1) { - message->what = B_REFS_RECEIVED; + + case CREATE_BOOKMARK: + _CreateBookmark(); + break; + case SHOW_BOOKMARKS: + _ShowBookmarks(); + break; + + case B_REFS_RECEIVED: + { + // Currently the only source of these messages is the bookmarks menu. + // Filter refs into URLs, this also gets rid of refs for folders. + // For clicks on sub-folders in the bookmarks menu, we have Tracker + // open the corresponding folder. + entry_ref ref; + uint32 addedCount = 0; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BEntry entry(&ref); + uint32 addedSubCount = 0; + if (entry.IsDirectory()) { + BDirectory directory(&entry); + _AddBookmarkURLsRecursively(directory, message, + addedSubCount); + } else { + BFile file(&ref, B_READ_ONLY); + BString url; + if (_ReadURLAttr(file, url)) { + message->AddString("url", url.String()); + addedSubCount++; + } + } + if (addedSubCount == 0) { + // Don't know what to do with this entry, just pass it + // on to the system to handle. Note that this may result + // in us opening other supported files via the application + // mechanism. + be_roster->Launch(&ref); + } + addedCount += addedSubCount; + } + message->RemoveName("refs"); + if (addedCount > 10) { + BString string; + string << "Do you want to open " << addedCount; + string << " bookmarks all at once?"; + BAlert* alert = new BAlert("Open bookmarks confirmation", + string.String(), "Cancel", "Open all"); + if (alert->Go() == 0) + break; + } be_app->PostMessage(message); break; } - entry_ref ref; - if (message->FindRef("refs", &ref) != B_OK) + case B_SIMPLE_DATA: + { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it + // (open one new page per ref). If there is one ref, open it in + // this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + CurrentWebView()->LoadURL(path.Path()); break; - BEntry entry(&ref, true); - BPath path; - if (!entry.Exists() || entry.GetPath(&path) != B_OK) - break; - CurrentWebView()->LoadURL(path.Path()); - break; - } - - case ZOOM_FACTOR_INCREASE: - CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); - break; - case ZOOM_FACTOR_DECREASE: - CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); - break; - case ZOOM_FACTOR_RESET: - CurrentWebView()->ResetZoomFactor(); - break; - case ZOOM_TEXT_ONLY: - fZoomTextOnly = !fZoomTextOnly; - fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); - // TODO: Would be nice to have an instant update if the page is already - // zoomed. - break; - - case TEXT_FIND_NEXT: - CurrentWebView()->FindString(fFindTextControl->Text(), true, - fFindCaseSensitiveCheckBox->Value()); - break; - case TEXT_FIND_PREVIOUS: - CurrentWebView()->FindString(fFindTextControl->Text(), false, - fFindCaseSensitiveCheckBox->Value()); - break; - case TEXT_SHOW_FIND_GROUP: - if (!fFindGroup->IsVisible()) - fFindGroup->SetVisible(true); - fFindTextControl->MakeFocus(true); - break; - case TEXT_HIDE_FIND_GROUP: - if (fFindGroup->IsVisible()) - fFindGroup->SetVisible(false); - break; - - case SHOW_DOWNLOAD_WINDOW: - case SHOW_SETTINGS_WINDOW: - message->AddUInt32("workspaces", Workspaces()); - be_app->PostMessage(message); - break; - - case CLOSE_TAB: - if (fTabManager->CountTabs() > 1) { - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = fTabManager->SelectedTabIndex(); - _ShutdownTab(index); - _UpdateTabGroupVisibility(); - } else - PostMessage(B_QUIT_REQUESTED); - break; - - case SELECT_TAB: { - int32 index; - if (message->FindInt32("tab index", &index) == B_OK - && fTabManager->SelectedTabIndex() != index - && fTabManager->CountTabs() > index) { - fTabManager->SelectTab(index); } - break; - } + case ZOOM_FACTOR_INCREASE: + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); + break; + case ZOOM_FACTOR_DECREASE: + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); + break; + case ZOOM_FACTOR_RESET: + CurrentWebView()->ResetZoomFactor(); + break; + case ZOOM_TEXT_ONLY: + fZoomTextOnly = !fZoomTextOnly; + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + // TODO: Would be nice to have an instant update if the page is + // already zoomed. + break; - case TAB_CHANGED: { - // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = -1; - _TabChanged(index); - break; - } + case TEXT_FIND_NEXT: + CurrentWebView()->FindString(fFindTextControl->Text(), true, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + CurrentWebView()->FindString(fFindTextControl->Text(), false, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!fFindGroup->IsVisible()) + fFindGroup->SetVisible(true); + fFindTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (fFindGroup->IsVisible()) + fFindGroup->SetVisible(false); + break; - default: - BWebWindow::MessageReceived(message); - break; + case SHOW_DOWNLOAD_WINDOW: + case SHOW_SETTINGS_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; + + case CLOSE_TAB: + if (fTabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = fTabManager->SelectedTabIndex(); + _ShutdownTab(index); + _UpdateTabGroupVisibility(); + } else + PostMessage(B_QUIT_REQUESTED); + break; + + case SELECT_TAB: + { + int32 index; + if (message->FindInt32("tab index", &index) == B_OK + && fTabManager->SelectedTabIndex() != index + && fTabManager->CountTabs() > index) { + fTabManager->SelectTab(index); + } + + break; + } + + case TAB_CHANGED: + { + // This message may be received also when the last tab closed, + // i.e. with index == -1. + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + _TabChanged(index); + break; + } + + case SETTINGS_VALUE_CHANGED: + { + BString name; + if (message->FindString("name", &name) != B_OK) + break; + bool flag; + if (name == kSettingsKeyShowTabsIfSinglePageOpen + && message->FindBool("value", &flag) == B_OK) { + if (fShowTabsIfSinglePageOpen != flag) { + fShowTabsIfSinglePageOpen = flag; + _UpdateTabGroupVisibility(); + } + } + break; + } + + default: + BWebWindow::MessageReceived(message); + break; } } @@ -898,7 +929,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, bool modalDialog, bool resizable) { if (windowFrame.IsValid()) { - BrowserWindow* window = new BrowserWindow(windowFrame, + BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, DoNotHaveToolbar, view); window->Show(); } else @@ -1166,7 +1197,8 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { -// fTabGroup->SetVisible(fTabManager->CountTabs() > 1); + fTabGroup->SetVisible(fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e1ec942b2e..3f6e0a12b1 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -45,10 +45,11 @@ class BPath; class BStatusBar; class BStringView; class BTextControl; +class BWebView; class IconButton; +class SettingsMessage; class TabManager; class TextControlCompleter; -class BWebView; enum ToolbarPolicy { HaveToolbar, @@ -70,6 +71,7 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, + SettingsMessage* appSettings, ToolbarPolicy = HaveToolbar, BWebView* webView = NULL); virtual ~BrowserWindow(); @@ -144,7 +146,6 @@ private: private: BMenu* fGoMenu; BMenuItem* fZoomTextOnlyMenuItem; - bool fZoomTextOnly; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; @@ -163,6 +164,10 @@ private: BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + + SettingsMessage* fAppSettings; + bool fZoomTextOnly; + bool fShowTabsIfSinglePageOpen; }; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp new file mode 100644 index 0000000000..7fe0c4e1e2 --- /dev/null +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h new file mode 100644 index 0000000000..584a320e86 --- /dev/null +++ b/src/apps/webpositive/SettingsKeys.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + + +extern const char* kSettingsKeyDownloadPath; +extern const char* kSettingsKeyShowTabsIfSinglePageOpen; + + +#endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 833924b7a2..8a7c4daa64 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -27,6 +27,7 @@ #include "SettingsWindow.h" #include +#include #include #include #include @@ -48,6 +49,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "FontSelectionView.h" +#include "SettingsKeys.h" #include "SettingsMessage.h" #include "WebSettings.h" @@ -64,6 +66,7 @@ enum { MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', MSG_GO_MENU_DAYS_CHANGED = 'digm', + MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', }; static const int32 kDefaultFontSize = 14; @@ -144,33 +147,39 @@ 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_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); - break; - } - case MSG_FIXED_FONT_SIZE_SELECTED: { - int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); - fFixedFontView->SetSize(size); - break; - } + case MSG_STANDARD_FONT_SIZE_SELECTED: + { + int32 size = _SizesMenuValue(fStandardSizesMenu->Menu()); + fStandardFontView->SetSize(size); + fSerifFontView->SetSize(size); + fSansSerifFontView->SetSize(size); + break; + } + case MSG_FIXED_FONT_SIZE_SELECTED: + { + int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); + fFixedFontView->SetSize(size); + break; + } - default: - BWindow::MessageReceived(message); - break; + case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: + // TODO: Some settings could change live, some others not? + break; + + default: + BWindow::MessageReceived(message); + break; } } @@ -236,6 +245,11 @@ fNewPageBehaviorMenu->SetEnabled(false); for (uchar i = '9' + 1; i <= 128; i++) fDaysInGoMenuControl->TextView()->DisallowChar(i); + fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", + TR("Show tabs if only page is open."), + new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); + fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); + BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) @@ -246,7 +260,9 @@ fNewPageBehaviorMenu->SetEnabled(false); .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 4, 2) + .Add(fShowTabsIfOnlyOnePage, 0, 4, 2) + + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) .SetInsets(spacing, spacing, spacing, spacing) ; @@ -323,7 +339,9 @@ SettingsWindow::_ApplySettings() fDaysInGoMenuControl->SetText(text.String()); BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); - fSettings->SetValue("download path", fDownloadFolderControl->Text()); + fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); + fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, + fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); @@ -354,6 +372,11 @@ SettingsWindow::_ApplySettings() void SettingsWindow::_RevertSettings() { + fDownloadFolderControl->SetText( + fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fShowTabsIfOnlyOnePage->SetValue( + fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + int32 defaultFontSize = fSettings->GetValue("standard font size", kDefaultFontSize); int32 defaultFixedFontSize = fSettings->GetValue("fixed font size", diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 124b85f7e6..1e9d7e3421 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,6 +30,7 @@ #include class BButton; +class BCheckBox; class BMenu; class BMenuField; class BMenuItem; @@ -73,6 +74,7 @@ private: BMenuItem* fNewPageBehaviorOpenSearchItem; BMenuItem* fNewPageBehaviorOpenBlankItem; BTextControl* fDaysInGoMenuControl; + BCheckBox* fShowTabsIfOnlyOnePage; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 27ddac2e6e5965d9c4237adfc98028e696fe3536 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:53:55 +0000 Subject: [PATCH 152/293] Use the new SettingsKeys.h also in the DownloadsWindow. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@394 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 225b3e931c..22a8b010ea 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -47,6 +47,7 @@ #include "BrowserApp.h" #include "DownloadProgressView.h" +#include "SettingsKeys.h" #include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -256,8 +257,8 @@ DownloadWindow::MessageReceived(BMessage* message) case SETTINGS_VALUE_CHANGED: { BString string; - if (message->FindString("name", &string) == B_OK - && string == "download path" + if (message->FindString("name", &string) == B_OK + && string == kSettingsKeyDownloadPath && message->FindString("value", &string) == B_OK) { fDownloadPath = string; } From 3ae87b10f1f7f6c44f6c488bc96b46a5eaa6c327 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:55:21 +0000 Subject: [PATCH 153/293] Replace the remaining places where the string was redefined. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@395 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- src/apps/webpositive/SettingsWindow.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 22a8b010ea..7fa39a6b0a 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -143,8 +143,9 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, BPath downloadPath; if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) downloadPath.SetTo("/boot/home/Desktop"); - fDownloadPath = settings->GetValue("download path", downloadPath.Path()); - settings->SetValue("download path", fDownloadPath); + fDownloadPath = settings->GetValue(kSettingsKeyDownloadPath, + downloadPath.Path()); + settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath); SetLayout(new BGroupLayout(B_VERTICAL)); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8a7c4daa64..2f4a463691 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -211,7 +211,8 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); - fDownloadFolderControl->SetText(fSettings->GetValue("download path", "")); + fDownloadFolderControl->SetText( + fSettings->GetValue(kSettingsKeyDownloadPath, "")); fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), NULL); From c373752f789002d5cf8675ef0f6c7bcec892783f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 00:00:24 +0000 Subject: [PATCH 154/293] Fixed a spelling error. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@396 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 2f4a463691..8591fd8c6a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -247,7 +247,7 @@ fNewPageBehaviorMenu->SetEnabled(false); fDaysInGoMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", - TR("Show tabs if only page is open."), + TR("Show tabs if only one page is open."), new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); From 845ec8e102a5530f5a1e3037f7c6e0fe571438e3 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 10:55:29 +0000 Subject: [PATCH 155/293] * Revised the application startup to check how many windows have been created at all. Open a blank page if no pages have been created from the arguments passed to the application. * If no pages have been created yet, don't offset the last known window frame. This fixes windows shifting over the screen from session to session. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@397 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 58 +++++++++++++++++++---------- src/apps/webpositive/BrowserApp.h | 2 + 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 1cade8cd09..a32bbd04c0 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -162,11 +162,13 @@ BrowserApp::ReadyToRun() fInitialized = true; + int32 pagesCreated = 0; if (fLaunchRefsMessage) { - RefsReceived(fLaunchRefsMessage); + _RefsReceived(fLaunchRefsMessage, &pagesCreated); delete fLaunchRefsMessage; fLaunchRefsMessage = 0; - } else { + } + if (pagesCreated == 0) { BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); } @@ -236,22 +238,7 @@ BrowserApp::RefsReceived(BMessage* message) return; } - 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); - } - - BString url; - for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) - _CreateNewPage(url); + _RefsReceived(message); } @@ -295,6 +282,36 @@ BrowserApp::QuitRequested() } +void +BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) +{ + int32 pagesCreated = 0; + + 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); + pagesCreated++; + } + + BString url; + for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) { + _CreateNewPage(url); + pagesCreated++; + } + + if (_pagesCreated != NULL) + *_pagesCreated = pagesCreated; +} + + void BrowserApp::_CreateNewPage(const BString& url) { @@ -323,7 +340,10 @@ BrowserApp::_CreateNewPage(const BString& url) void BrowserApp::_CreateNewWindow(const BString& url) { - fLastWindowFrame.OffsetBy(20, 20); + // 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); diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index dfc9433e5e..f83d379a63 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -53,6 +53,8 @@ public: virtual bool QuitRequested(); private: + void _RefsReceived(BMessage* message, + int32* pagesCreated = NULL); void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, From 8061d9ebfffff91d7a4fc1b8a2d8823aa36a83c2 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 12:46:39 +0000 Subject: [PATCH 156/293] In BrowserWindow::_TabChanged(), the BWebView could be NULL. Also check if there is a focused view set at all. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@398 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a5d8fa2671..c8369b2af1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1228,17 +1228,19 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - PageUserData* userData = static_cast(webView->GetUserData()); - if (userData) - userData->FocusedView()->MakeFocus(true); - else - webView->MakeFocus(true); - if (webView) _UpdateTitle(webView->MainFrameTitle()); else _UpdateTitle(""); + if (webView) { + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData && userData->FocusedView() != NULL) + userData->FocusedView()->MakeFocus(true); + else + webView->MakeFocus(true); + fURLTextControl->SetText(webView->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. From 1137289fbc2ccb4f5a5417f5d4007c2fed311a99 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 12:58:22 +0000 Subject: [PATCH 157/293] Simplify the code. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@399 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c8369b2af1..4a4be2ba93 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1228,12 +1228,9 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - if (webView) - _UpdateTitle(webView->MainFrameTitle()); - else - _UpdateTitle(""); - if (webView) { + _UpdateTitle(webView->MainFrameTitle()); + PageUserData* userData = static_cast( webView->GetUserData()); if (userData && userData->FocusedView() != NULL) @@ -1245,7 +1242,8 @@ BrowserWindow::_TabChanged(int32 index) // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); - } + } else + _UpdateTitle(""); } From 1cad765a3b1d712ca669d75e33e24083d14bdf74 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 13:00:55 +0000 Subject: [PATCH 158/293] Maybe CurrentWebView() is NULL too... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@400 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4a4be2ba93..b9ef820438 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1224,7 +1224,8 @@ BrowserWindow::_TabChanged(int32 index) if (webView == CurrentWebView()) return; - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (CurrentWebView() != NULL) + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); SetCurrentWebView(webView); From 406b9363222b797a5f94dba7c33d2cf638414666 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 13:07:44 +0000 Subject: [PATCH 159/293] Selecting the tab for which authentication was requested didn't work anymore. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@401 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b9ef820438..f41760328d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1168,7 +1168,13 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, { // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { - fTabManager->SelectTab(view); + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) { + // page seems to be gone already? + return false; + } + fTabManager->SelectTab(tabIndex); + _TabChanged(tabIndex); UpdateIfNeeded(); } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); @@ -1210,7 +1216,7 @@ BrowserWindow::_ShutdownTab(int32 index) { BView* view = fTabManager->RemoveTab(index); BWebView* webView = dynamic_cast(view); - if (webView) + if (webView != NULL) webView->Shutdown(); else delete view; @@ -1229,12 +1235,12 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - if (webView) { + if (webView != NULL) { _UpdateTitle(webView->MainFrameTitle()); PageUserData* userData = static_cast( webView->GetUserData()); - if (userData && userData->FocusedView() != NULL) + if (userData != NULL && userData->FocusedView() != NULL) userData->FocusedView()->MakeFocus(true); else webView->MakeFocus(true); From 312655fb6f521a6a769e3d7dd4cb908708848f29 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 8 Apr 2010 12:42:58 +0000 Subject: [PATCH 160/293] * Renamed TextControlCompleter to TextViewCompleter, since it actually only works with the BTextView. * Factored out the URL text handling into a new class URLInputGroup, which is used instead of a plain BTextControl, but currently works much the same way. It's a BGroupView though and allows easy addition of other controls and items into the URL text field. * Moved baseURL() method into it's own file, since it's used from multiple places now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@402 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 147 +------ src/apps/webpositive/BrowserWindow.h | 5 +- src/apps/webpositive/URLInputGroup.cpp | 384 ++++++++++++++++++ src/apps/webpositive/URLInputGroup.h | 35 ++ ...rolCompleter.cpp => TextViewCompleter.cpp} | 55 ++- ...ControlCompleter.h => TextViewCompleter.h} | 20 +- src/apps/webpositive/support/BaseURL.cpp | 18 + src/apps/webpositive/support/BaseURL.h | 14 + 8 files changed, 506 insertions(+), 172 deletions(-) create mode 100644 src/apps/webpositive/URLInputGroup.cpp create mode 100644 src/apps/webpositive/URLInputGroup.h rename src/apps/webpositive/autocompletion/{TextControlCompleter.cpp => TextViewCompleter.cpp} (53%) rename src/apps/webpositive/autocompletion/{TextControlCompleter.h => TextViewCompleter.h} (69%) create mode 100644 src/apps/webpositive/support/BaseURL.cpp create mode 100644 src/apps/webpositive/support/BaseURL.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f41760328d..ae574c6f80 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -34,13 +34,14 @@ #include "BrowserWindow.h" #include "AuthenticationPanel.h" +#include "BaseURL.h" #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" #include "NavMenu.h" #include "SettingsKeys.h" #include "SettingsMessage.h" -#include "TextControlCompleter.h" +#include "URLInputGroup.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -107,112 +108,6 @@ layoutItemFor(BView* view) } -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; -}; - - -static 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; -} - - -class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { - virtual void FetchChoicesFor(const BString& pattern) - { - int32 count = CountChoices(); - for (int32 i = 0; i < count; i++) { - delete reinterpret_cast( - 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( - fChoices.ItemAt(index)); - } - - static int _CompareChoices(const void* a, const void* b) - { - const URLChoice* aChoice = *reinterpret_cast(a); - const URLChoice* bChoice = *reinterpret_cast(b); - if (*aChoice < *bChoice) - return -1; - else if (*aChoice == *bChoice) - return 0; - return 1; - } - -private: - BList fChoices; -}; - - class BookmarkMenu : public BNavMenu { public: BookmarkMenu(const char* title, BHandler* target, const entry_ref* navDir) @@ -349,8 +244,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->TrimIcon(); // URL - fURLTextControl = new BTextControl("url", "", "", NULL); - fURLTextControl->SetDivider(50.0); + fURLInputGroup = new URLInputGroup(); // Go fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); @@ -396,7 +290,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(fBackButton, 0, 0) .Add(fForwardButton, 1, 0) .Add(fStopButton, 2, 0) - .Add(fURLTextControl, 3, 0) + .Add(fURLInputGroup, 3, 0) .Add(fGoButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) @@ -423,10 +317,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(statusGroup) ); - fURLTextControl->MakeFocus(true); - - fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel()); + fURLInputGroup->MakeFocus(true); fMenuGroup = layoutItemFor(mainMenu); fTabGroup = layoutItemFor(fTabManager->TabGroup()); @@ -471,7 +362,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BrowserWindow::~BrowserWindow() { fAppSettings->RemoveListener(BMessenger(this)); - delete fURLAutoCompleter; delete fTabManager; } @@ -484,7 +374,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK && message->FindInt32("modifiers", &modifiers) == B_OK) { - if (fURLTextControl && target == fURLTextControl->TextView()) { + if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there when @@ -512,12 +402,10 @@ BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { case OPEN_LOCATION: - if (fURLTextControl) { - if (fURLTextControl->TextView()->IsFocus()) - fURLTextControl->TextView()->SelectAll(); - else - fURLTextControl->MakeFocus(true); - } + if (fURLInputGroup->TextView()->IsFocus()) + fURLInputGroup->TextView()->SelectAll(); + else + fURLInputGroup->MakeFocus(true); break; case RELOAD: CurrentWebView()->Reload(); @@ -526,7 +414,7 @@ BrowserWindow::MessageReceived(BMessage* message) { BString url; if (message->FindString("url", &url) != B_OK) - url = fURLTextControl->Text(); + url = fURLInputGroup->Text(); fTabManager->SetTabIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; @@ -889,10 +777,8 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); webView->WebPage()->ResendNotifications(); - if (fURLTextControl) { - fURLTextControl->SetText(url.String()); - fURLTextControl->MakeFocus(true); - } + fURLInputGroup->SetText(url.String()); + fURLInputGroup->MakeFocus(true); } _UpdateTabGroupVisibility(); @@ -967,8 +853,7 @@ BrowserWindow::LoadCommitted(const BString& url, BWebView* view) return; // This hook is invoked when the load is commited. - if (fURLTextControl) - fURLTextControl->SetText(url.String()); + fURLInputGroup->SetText(url.String()); BString status("Loading: "); status << url; @@ -1170,7 +1055,7 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, if (view != CurrentWebView()) { int32 tabIndex = fTabManager->TabForView(view); if (tabIndex < 0) { - // page seems to be gone already? + // Page seems to be gone already? return false; } fTabManager->SelectTab(tabIndex); @@ -1245,7 +1130,7 @@ BrowserWindow::_TabChanged(int32 index) else webView->MakeFocus(true); - fURLTextControl->SetText(webView->MainFrameURL()); + fURLInputGroup->SetText(webView->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 3f6e0a12b1..6146c8ecb2 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -49,7 +49,7 @@ class BWebView; class IconButton; class SettingsMessage; class TabManager; -class TextControlCompleter; +class URLInputGroup; enum ToolbarPolicy { HaveToolbar, @@ -150,8 +150,7 @@ private: IconButton* fForwardButton; IconButton* fStopButton; BButton* fGoButton; - BTextControl* fURLTextControl; - TextControlCompleter* fURLAutoCompleter; + URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp new file mode 100644 index 0000000000..07b4772c39 --- /dev/null +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -0,0 +1,384 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "URLInputGroup.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "BaseURL.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( + 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( + fChoices.ItemAt(index)); + } + + static int _CompareChoices(const void* a, const void* b) + { + const URLChoice* aChoice + = *reinterpret_cast(a); + const URLChoice* bChoice + = *reinterpret_cast(b); + if (*aChoice < *bChoice) + return -1; + else if (*aChoice == *bChoice) + return 0; + return 1; + } + +private: + BList fChoices; +}; + + +// #pragma mark - URLTextView + + +static const float kHorizontalTextRectInset = 3.0; + + +class URLInputGroup::URLTextView : public BTextView { +public: + URLTextView(URLInputGroup* parent); + virtual ~URLTextView(); + + 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(); + +protected: + virtual void InsertText(const char* inText, int32 inLength, + int32 inOffset, + const text_run_array* inRuns); +private: + void _AlignTextRect(); + +private: + URLInputGroup* fURLInputGroup; + TextViewCompleter* fURLAutoCompleter; + BString fPreviousText; +}; + + +URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) + : + BTextView("url"), + fURLInputGroup(parent), + fURLAutoCompleter(new TextViewCompleter(this, + new BrowsingHistoryChoiceModel())), + fPreviousText("") +{ + MakeResizable(true); +} + + +URLInputGroup::URLTextView::~URLTextView() +{ + delete fURLAutoCompleter; +} + + +void +URLInputGroup::URLTextView::FrameResized(float width, float height) +{ + BTextView::FrameResized(width, height); + _AlignTextRect(); +} + + +void +URLInputGroup::URLTextView::MouseDown(BPoint where) +{ + if (!IsFocus()) { + MakeFocus(true); + return; + } + + // Only pass through to base class if we already have focus. + 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; + + 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::InsertText(const char* inText, int32 inLength, + int32 inOffset, const text_run_array* inRuns) +{ + char* buffer = NULL; + + if (strpbrk(inText, "\r\n") && inLength <= 1024) { + buffer = (char*)malloc(inLength); + + if (buffer) { + strcpy(buffer, inText); + + for (int32 i = 0; i < inLength; i++) { + if (buffer[i] == '\r' || buffer[i] == '\n') + buffer[i] = ' '; + } + } + } + + BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset, + inRuns); + + free(buffer); +} + + +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); +} + + +// #pragma mark - URLInputGroup + + +URLInputGroup::URLInputGroup() + : + BGroupView(B_HORIZONTAL), + fWindowActive(false) +{ + GroupLayout()->SetInsets(2, 2, 2, 2); + + fTextView = new URLTextView(this); + AddChild(fTextView); + + 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) +{ + fTextView->SetText(text); +} + + +const char* +URLInputGroup::Text() const +{ + return fTextView->Text(); +} + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h new file mode 100644 index 0000000000..5f75590c6a --- /dev/null +++ b/src/apps/webpositive/URLInputGroup.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef URL_INPUT_GROUP_H +#define URL_INPUT_GROUP_H + +#include + +class BTextView; + + +class URLInputGroup : public BGroupView { +public: + URLInputGroup(); + 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; + +private: + class URLTextView; + + URLTextView* fTextView; + bool fWindowActive; +}; + +#endif // URL_INPUT_GROUP_H + diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp similarity index 53% rename from src/apps/webpositive/autocompletion/TextControlCompleter.cpp rename to src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 552c8b5f5d..5ae515b529 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -6,7 +6,7 @@ * Oliver Tappe */ -#include "TextControlCompleter.h" +#include "TextViewCompleter.h" #include #include @@ -15,75 +15,74 @@ #include "AutoCompleterDefaultImpl.h" -// #pragma mark - TextControlWrapper +// #pragma mark - TextViewWrapper -TextControlCompleter::TextControlWrapper::TextControlWrapper( - BTextControl* textControl) +TextViewCompleter::TextViewWrapper::TextViewWrapper(BTextView* textView) : - fTextControl(textControl) + fTextView(textView) { } void -TextControlCompleter::TextControlWrapper::GetEditViewState(BString& text, +TextViewCompleter::TextViewWrapper::GetEditViewState(BString& text, int32* caretPos) { - if (fTextControl && fTextControl->LockLooper()) { - text = fTextControl->Text(); + if (fTextView && fTextView->LockLooper()) { + text = fTextView->Text(); if (caretPos) { int32 end; - fTextControl->TextView()->GetSelection(caretPos, &end); + fTextView->GetSelection(caretPos, &end); } - fTextControl->UnlockLooper(); + fTextView->UnlockLooper(); } } void -TextControlCompleter::TextControlWrapper::SetEditViewState(const BString& text, +TextViewCompleter::TextViewWrapper::SetEditViewState(const BString& text, int32 caretPos, int32 selectionLength) { - if (fTextControl && fTextControl->LockLooper()) { - fTextControl->TextView()->SetText(text.String(), text.Length()); - fTextControl->TextView()->Select(caretPos, caretPos + selectionLength); - fTextControl->TextView()->ScrollToSelection(); - fTextControl->UnlockLooper(); + if (fTextView && fTextView->LockLooper()) { + fTextView->SetText(text.String(), text.Length()); + fTextView->Select(caretPos, caretPos + selectionLength); + fTextView->ScrollToSelection(); + fTextView->UnlockLooper(); } } BRect -TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() +TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() { - BRect frame = fTextControl->TextView()->Bounds(); - frame = fTextControl->TextView()->ConvertToScreen(frame); + BRect frame = fTextView->Bounds(); + frame = fTextView->ConvertToScreen(frame); frame.InsetBy(0, -3); return frame; } -TextControlCompleter::TextControlCompleter(BTextControl* textControl, - ChoiceModel* model, PatternSelector* patternSelector) +TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, + PatternSelector* patternSelector) : - BAutoCompleter(new TextControlWrapper(textControl), model, + BAutoCompleter(new TextViewWrapper(textView), model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), - fTextControl(textControl) + fTextView(textView) { - fTextControl->TextView()->AddFilter(this); + fTextView->AddFilter(this); } -TextControlCompleter::~TextControlCompleter() +TextViewCompleter::~TextViewCompleter() { - fTextControl->TextView()->RemoveFilter(this); + fTextView->RemoveFilter(this); } filter_result -TextControlCompleter::Filter(BMessage* message, BHandler** target) +TextViewCompleter::Filter(BMessage* message, BHandler** target) { const char* bytes; int32 modifiers; @@ -91,7 +90,7 @@ TextControlCompleter::Filter(BMessage* message, BHandler** target) || message->FindInt32("modifiers", &modifiers) != B_OK) { return B_DISPATCH_MESSAGE; } - + switch (bytes[0]) { case B_UP_ARROW: SelectPrevious(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h similarity index 69% rename from src/apps/webpositive/autocompletion/TextControlCompleter.h rename to src/apps/webpositive/autocompletion/TextViewCompleter.h index 89c5125f2e..a325603309 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -13,31 +13,31 @@ #include "AutoCompleter.h" -class BTextControl; +class BTextView; -class TextControlCompleter : protected BAutoCompleter, public BMessageFilter { +class TextViewCompleter : protected BAutoCompleter, public BMessageFilter { public: - TextControlCompleter(BTextControl* textControl, + TextViewCompleter(BTextView* textView, ChoiceModel* choiceModel = NULL, PatternSelector* patternSelector = NULL); - virtual ~TextControlCompleter(); - + virtual ~TextViewCompleter(); + private: virtual filter_result Filter(BMessage* message, BHandler** target); - - class TextControlWrapper : public EditView { + + class TextViewWrapper : public EditView { public: - TextControlWrapper(BTextControl* textControl); + 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: - BTextControl* fTextControl; + BTextView* fTextView; }; private: - BTextControl* fTextControl; + BTextView* fTextView; }; #endif // TEXT_CONTROL_COMPLETER_H diff --git a/src/apps/webpositive/support/BaseURL.cpp b/src/apps/webpositive/support/BaseURL.cpp new file mode 100644 index 0000000000..4d2f47cd29 --- /dev/null +++ b/src/apps/webpositive/support/BaseURL.cpp @@ -0,0 +1,18 @@ +/* + * Copyright 2010 Stephan Aßmus + * 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; +} + diff --git a/src/apps/webpositive/support/BaseURL.h b/src/apps/webpositive/support/BaseURL.h new file mode 100644 index 0000000000..b4589ef58f --- /dev/null +++ b/src/apps/webpositive/support/BaseURL.h @@ -0,0 +1,14 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef BASE_URL_H +#define BASE_URL_H + +#include + + +BString baseURL(const BString string); + + +#endif // BASE_URL_H From ad7c99c0ca4493fe060f90ec7ee8aae72913e640 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 8 Apr 2010 15:52:28 +0000 Subject: [PATCH 161/293] * Integrated the Go button into the URL text field. * Added a context menu to the URL input for integration with the system clipboard when you want to use the mouse only. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@403 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 +- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/URLInputGroup.cpp | 219 ++++++++++++++++++++++++- src/apps/webpositive/URLInputGroup.h | 6 +- src/apps/webpositive/WebPositive.rdef | 50 +++++- 5 files changed, 273 insertions(+), 17 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ae574c6f80..2b5bce1fb3 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -243,11 +243,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->SetIcon(204); fStopButton->TrimIcon(); - // URL - fURLInputGroup = new URLInputGroup(); - - // Go - fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); + // URL input group + fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); // Status Bar fStatusText = new BStringView("status", ""); @@ -291,7 +288,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(fForwardButton, 1, 0) .Add(fStopButton, 2, 0) .Add(fURLInputGroup, 3, 0) - .Add(fGoButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -381,11 +377,11 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) // the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. - fGoButton->SetValue(B_CONTROL_ON); + fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); UpdateIfNeeded(); - fGoButton->Invoke(); + fURLInputGroup->GoButton()->Invoke(); snooze(1000); - fGoButton->SetValue(B_CONTROL_OFF); + fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); } } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { PostMessage(GO_BACK); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 6146c8ecb2..c6c91a88c9 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -149,7 +149,6 @@ private: IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; - BButton* fGoButton; URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 07b4772c39..32cbffd55b 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -5,13 +5,18 @@ #include "URLInputGroup.h" +#include +#include #include +#include #include #include #include #include #include +#include #include +#include #include #include @@ -127,10 +132,14 @@ static const float kHorizontalTextRectInset = 3.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); @@ -171,6 +180,20 @@ URLInputGroup::URLTextView::~URLTextView() } +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) { @@ -182,12 +205,52 @@ URLInputGroup::URLTextView::FrameResized(float width, float height) void URLInputGroup::URLTextView::MouseDown(BPoint where) { - if (!IsFocus()) { + 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); } @@ -295,10 +358,145 @@ URLInputGroup::URLTextView::_AlignTextRect() } +// #pragma mark - GoButton + + +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, 0xc0, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, 0xd5, 0xa6, 0xff, + 0x4a, 0x67, 0x50, 0xff, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0xb2, 0xf9, 0xc0, 0xff, 0x88, 0xbb, 0x91, 0xff, + 0x2e, 0x3d, 0x32, 0xff, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, + 0x73, 0xfa, 0x8c, 0xff, 0x9f, 0xf9, 0xae, 0xff, 0xac, 0xed, 0xb7, 0xff, 0x63, 0x96, 0x6d, 0xff, + 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0x5d, 0xfc, 0x7b, 0xff, 0x5d, 0xfc, 0x7b, 0xff, + 0x72, 0xf9, 0x88, 0xff, 0x6d, 0xe5, 0x82, 0xff, 0x50, 0xbf, 0x65, 0xff, 0x27, 0x63, 0x32, 0xff, + 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb4, 0xf8, 0xc0, 0xff, + 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfb, 0x76, 0xff, + 0x4a, 0xe8, 0x67, 0xff, 0x32, 0xcc, 0x50, 0xff, 0x27, 0x9e, 0x3d, 0xff, 0x15, 0x3d, 0x15, 0xff, + 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xa2, 0xf2, 0xb0, 0xff, 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xfa, 0x54, 0xff, + 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xf9, 0x54, 0xff, 0x27, 0xe4, 0x48, 0xff, 0x15, 0xc5, 0x38, 0xff, + 0x15, 0x98, 0x2e, 0xff, 0x00, 0x3b, 0x15, 0xff, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x26, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xe9, 0x99, 0xff, + 0x15, 0xf9, 0x40, 0xff, 0x15, 0xf9, 0x40, 0xff, 0x15, 0xed, 0x3d, 0xff, 0x00, 0xc8, 0x2b, 0xff, + 0x00, 0xa5, 0x22, 0xff, 0x00, 0x57, 0x15, 0xff, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x63, + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x72, 0xe0, 0x86, 0xff, 0x22, 0xf5, 0x42, 0xff, 0x27, 0xda, 0x46, 0xff, + 0x15, 0xb6, 0x32, 0xff, 0x00, 0x74, 0x1c, 0xff, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x81, + 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x5f, 0xda, 0x76, 0xff, + 0x42, 0xd2, 0x5a, 0xff, 0x22, 0x95, 0x35, 0xff, 0x00, 0x2e, 0x00, 0xff, 0x00, 0x00, 0x00, 0xa2, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x46, 0xb6, 0x5c, 0xff, 0x1c, 0x54, 0x22, 0xff, 0x00, 0x00, 0x00, 0xc4, + 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xde, + 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +class BitmapButton : public BButton { + static const float kFrameInset = 2; + +public: + BitmapButton(const char* resourceName, BMessage* message) + : + BButton("", message), + fBitmap(BTranslationUtils::GetBitmap(resourceName)) + { + } + + 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)) + { + memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength()); + } + + ~BitmapButton() + { + delete fBitmap; + } + + virtual BSize 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; + } + + 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); + uint32 flags = be_control_look->Flags(this); + + be_control_look->DrawButtonBackground(this, bounds, updateRect, base, + flags); + + SetDrawingMode(B_OP_ALPHA); + + if (!IsEnabled()) { + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + SetHighColor(0, 0, 0, 120); + } + + BPoint bitmapLocation(kFrameInset, kFrameInset); + if (Value() == B_CONTROL_ON) + bitmapLocation += BPoint(1, 1); + + DrawBitmap(fBitmap, bitmapLocation); + } + +private: + BBitmap* fBitmap; +}; + + // #pragma mark - URLInputGroup -URLInputGroup::URLInputGroup() +URLInputGroup::URLInputGroup(BMessage* goMessage) : BGroupView(B_HORIZONTAL), fWindowActive(false) @@ -308,6 +506,15 @@ URLInputGroup::URLInputGroup() 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.0); + SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); SetLowColor(ViewColor()); SetViewColor(B_TRANSPARENT_COLOR); @@ -382,3 +589,11 @@ URLInputGroup::Text() const return fTextView->Text(); } + +BButton* +URLInputGroup::GoButton() const +{ + return fGoButton; +} + + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h index 5f75590c6a..105b76d932 100644 --- a/src/apps/webpositive/URLInputGroup.h +++ b/src/apps/webpositive/URLInputGroup.h @@ -7,12 +7,13 @@ #include +class BButton; class BTextView; class URLInputGroup : public BGroupView { public: - URLInputGroup(); + URLInputGroup(BMessage* goMessage); virtual ~URLInputGroup(); virtual void AttachedToWindow(); @@ -24,10 +25,13 @@ public: void SetText(const char* text); const char* Text() const; + BButton* GoButton() const; + private: class URLTextView; URLTextView* fTextView; + BButton* fGoButton; bool fWindowActive; }; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index f741a6a3e9..5734330206 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -252,7 +252,7 @@ resource vector_icon { $"44013402360000000000000000360000485000466000" }; -resource(201) #'VICN' array { +resource(201, "kActionBack") #'VICN' array { $"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" $"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF" $"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585" @@ -265,7 +265,7 @@ resource(201) #'VICN' array { $"05000A06020607100117812004" }; -resource(202) #'VICN' array { +resource(202, "kActionForward") #'VICN' array { $"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" $"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF" $"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD" @@ -275,7 +275,7 @@ resource(202) #'VICN' array { $"0A020102000A030103000A040104100117812004" }; -resource(203) #'VICN' array { +resource(203, "kActionForward2") #'VICN' array { $"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9" $"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF" $"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468" @@ -288,7 +288,7 @@ resource(203) #'VICN' array { $"000A06020607100117812004" }; -resource(204) #'VICN' array { +resource(204, "kActionStop") #'VICN' array { $"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E" $"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D" $"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478" @@ -301,3 +301,45 @@ resource(204) #'VICN' array { $"000A0503070809100117810004" }; +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" + } +}; + + From 3aa3e03460eba4d65982ec900b065e69deacd643 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 9 Apr 2010 11:12:12 +0000 Subject: [PATCH 162/293] Adopt the URL also when requesting the URL, before it is commited. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@404 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 2b5bce1fb3..c397962a5f 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -836,6 +836,11 @@ BrowserWindow::CloseWindowRequested(BWebView* view) void BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { + if (view != CurrentWebView()) + return; + + fURLInputGroup->SetText(url.String()); + BString status("Requesting: "); status << url; view->WebPage()->SetStatusMessage(status); From 560610f70eb60020d17ec3c2889357b18aa4e322 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 11 Apr 2010 23:21:45 +0000 Subject: [PATCH 163/293] Don't overwrite memory when pressing return in the URL text input. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@405 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 32cbffd55b..1f69f60538 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -320,10 +320,10 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, char* buffer = NULL; if (strpbrk(inText, "\r\n") && inLength <= 1024) { - buffer = (char*)malloc(inLength); + buffer = (char*)malloc(inLength + 1); if (buffer) { - strcpy(buffer, inText); + strlcpy(buffer, inText, inLength); for (int32 i = 0; i < inLength; i++) { if (buffer[i] == '\r' || buffer[i] == '\n') From f9977c07c19bfe294637ac51b3c64aa237b9a300 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 16:16:40 +0000 Subject: [PATCH 164/293] strlcpy() takes buffer size, not char count, and will copy buffer size - 1 chars at max and terminate the buffer. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@406 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 1f69f60538..35a6130181 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -323,7 +323,7 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, buffer = (char*)malloc(inLength + 1); if (buffer) { - strlcpy(buffer, inText, inLength); + strlcpy(buffer, inText, inLength + 1); for (int32 i = 0; i < inLength; i++) { if (buffer[i] == '\r' || buffer[i] == '\n') From a26e66b548662dc307869b11f411b6ce019ab3ae Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 16:57:03 +0000 Subject: [PATCH 165/293] One more round of simplification and fixing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@407 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 30 +++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 35a6130181..57c1d8baa7 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -317,25 +317,19 @@ void URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns) { - char* buffer = NULL; - - if (strpbrk(inText, "\r\n") && inLength <= 1024) { - buffer = (char*)malloc(inLength + 1); - - if (buffer) { - strlcpy(buffer, inText, inLength + 1); - - for (int32 i = 0; i < inLength; i++) { - if (buffer[i] == '\r' || buffer[i] == '\n') - buffer[i] = ' '; - } - } + // 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); } - - BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset, - inRuns); - - free(buffer); } From 0ef19ef7e12beb734510ed8bfd00a688300bdc9d Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 17:44:22 +0000 Subject: [PATCH 166/293] Fix the cmd-arrow left/right for go back/forward actions. Truncate the modifiers to just the part that describes the modifier keys in general. What's left should be exactly B_COMMAND_KEY. This fixes the workspace switching short-cut to trigger page history navigation WebPositive. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@408 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c397962a5f..5c8beb644e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -366,15 +366,21 @@ void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { const char* bytes; - int32 modifiers; + uint32 modifiers; if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK - && message->FindInt32("modifiers", &modifiers) == B_OK) { - if (target == fURLInputGroup->TextView()) { + && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { + + modifiers = modifiers & 0x000000ff; + if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) + PostMessage(GO_BACK); + else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) + PostMessage(GO_FORWARD); + else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the - // address bar, as opposed to trying to load whatever is in there when - // the text control just goes out of focus. + // address bar, as opposed to trying to load whatever is in there + // when the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); @@ -383,10 +389,6 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) snooze(1000); fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); } - } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { - PostMessage(GO_BACK); - } else if (bytes[0] == B_RIGHT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { - PostMessage(GO_FORWARD); } } BWebWindow::DispatchMessage(message, target); From 6d9387446962660835431fdf3b94d04884c49700 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 13 Apr 2010 23:15:23 +0000 Subject: [PATCH 167/293] * Add a flag "activate" to WindowFeatures and set it to true by default. It's supposed to allow specifying whether the new window/page shall be activated or not. * In ContextMenuController, when creating a new page from a link, specify that it shall not be activated. * Handle the new flag in the WebKit layer. -> "Open link in tab" from the context menu no longer selects the new tab, but opens it "in the background". git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@414 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++-- src/apps/webpositive/BrowserWindow.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5c8beb644e..ac030f2f9d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -810,14 +810,14 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) void BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, - bool modalDialog, bool resizable) + bool modalDialog, bool resizable, bool activate) { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, DoNotHaveToolbar, view); window->Show(); } else - CreateNewTab(BString(), true, view); + CreateNewTab(BString(), activate, view); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c6c91a88c9..124144cffb 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -94,7 +94,7 @@ private: virtual void CloseWindowRequested(BWebView* view); virtual void NewPageCreated(BWebView* view, BRect windowFrame, bool modalDialog, - bool resizable); + bool resizable, bool activate); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, From 029353b44c63fa39a9135f36f225bfac5daed34b Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 15 Apr 2010 12:19:16 +0000 Subject: [PATCH 168/293] * Reworded defines in Jamfiles to make them more readable. * Split WebTabView into several files in a new sub-folder "tabview". * Implemented scrolling the tab view left/right when there are more tabs than fit into the view. * Fixed graphic glitches in the TabContainerView when the window is resized, the space behind the last tab was not managed properly. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@416 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 520 ++++++++ .../webpositive/tabview/TabContainerView.h | 102 ++ .../TabManager.cpp} | 1052 ++++------------- .../{WebTabView.h => tabview/TabManager.h} | 3 +- src/apps/webpositive/tabview/TabView.cpp | 366 ++++++ src/apps/webpositive/tabview/TabView.h | 122 ++ 6 files changed, 1330 insertions(+), 835 deletions(-) create mode 100644 src/apps/webpositive/tabview/TabContainerView.cpp create mode 100644 src/apps/webpositive/tabview/TabContainerView.h rename src/apps/webpositive/{WebTabView.cpp => tabview/TabManager.cpp} (50%) rename src/apps/webpositive/{WebTabView.h => tabview/TabManager.h} (97%) create mode 100644 src/apps/webpositive/tabview/TabView.cpp create mode 100644 src/apps/webpositive/tabview/TabView.h diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp new file mode 100644 index 0000000000..a4c26ddb2d --- /dev/null +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TabView.h" + + +static const float kLeftTabInset = 4; + + +TabContainerView::TabContainerView(Controller* controller) + : + BGroupView(B_HORIZONTAL), + 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( + 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 (clicks > 1) + fClickCount++; + else + fClickCount = 1; + } +} + + +void +TabContainerView::MouseUp(BPoint where) +{ + fMouseDown = false; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseUp(where); + else if (fClickCount > 1) { + fClickCount = 0; + fController->DoubleClickOutsideTabs(); + } +} + + +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(GroupLayout()->ItemAt(index - 1)); + if (item) + item->Parent()->SetIsLast(false); + } + + SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex()); + _ValidateTabVisibility(); +} + +TabView* +TabContainerView::RemoveTab(int32 index) +{ + TabLayoutItem* item + = dynamic_cast(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(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(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( + 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( + 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()); + + fController->TabSelected(index); + } +} + + +void +TabContainerView::SetTabLabel(int32 tabIndex, const char* label) +{ + TabLayoutItem* item = dynamic_cast( + 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( + 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( + 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( + layout->ItemAt(i)); + if (item && item->IsVisible() && item->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 && 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); + } +} + + +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( + 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); +} + diff --git a/src/apps/webpositive/tabview/TabContainerView.h b/src/apps/webpositive/tabview/TabContainerView.h new file mode 100644 index 0000000000..13815d1592 --- /dev/null +++ b/src/apps/webpositive/tabview/TabContainerView.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + + +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; + }; + +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 diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/tabview/TabManager.cpp similarity index 50% rename from src/apps/webpositive/WebTabView.cpp rename to src/apps/webpositive/tabview/TabManager.cpp index d953d2ee99..814496e582 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -26,9 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WebTabView.h" +#include "TabManager.h" + +#include -#include "WebView.h" #include #include #include @@ -39,716 +40,245 @@ #include #include #include -#include + +#include "TabContainerView.h" +#include "TabView.h" -class TabView; -class TabContainerView; +// #pragma mark - Helper classes -class TabLayoutItem : public BAbstractLayoutItem { +class TabButton : public BButton { public: - TabLayoutItem(TabView* parent); + TabButton(BMessage* message) + : BButton("", message) + { + } - virtual bool IsVisible(); - virtual void SetVisible(bool visible); + virtual BSize MinSize() + { + return BSize(12, 12); + } - virtual BRect Frame(); - virtual void SetFrame(BRect frame); + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } - virtual BView* View(); + virtual BSize PreferredSize() + { + return MinSize(); + } - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); + 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); + } - TabView* Parent() const; + 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); + } -private: - TabView* fParent; - BRect fFrame; + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + } }; -class TabView { +class ScrollLeftTabButton : public TabButton { public: - TabView(); - virtual ~TabView(); + ScrollLeftTabButton(BMessage* message) + : TabButton(message) + { + } - 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; + 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 TabContainerView : public BGroupView { +class ScrollRightTabButton : public TabButton { public: - class Controller { - public: - virtual void TabSelected(int32 tabIndex) = 0; - virtual bool HasFrames() = 0; - virtual TabView* CreateTabView() = 0; - virtual void DoubleClickOutsideTabs() = 0; - }; + ScrollRightTabButton(BMessage* message) + : TabButton(message) + { + } -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); - -private: - TabView* _TabAt(const BPoint& where) const; - void _MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - -private: - TabView* fLastMouseEventTab; - bool fMouseDown; - uint32 fClickCount; - TabView* fSelectedTab; - Controller* fController; + 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); + } }; -// #pragma mark - TabContainerView - - -static const float kLeftTabInset = 4; - - -TabContainerView::TabContainerView(Controller* controller) - : - BGroupView(B_HORIZONTAL), - fLastMouseEventTab(NULL), - fMouseDown(false), - fClickCount(0), - fSelectedTab(NULL), - fController(controller) -{ - SetFlags(Flags() | B_WILL_DRAW); - 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( - layout->ItemAt(i)); - if (!item) - continue; - item->Parent()->Draw(updateRect); - frame.left = item->Frame().right + 1; +class NewTabButton : public TabButton { +public: + NewTabButton(BMessage* message) + : TabButton(message) + { + SetToolTip("New tab (Cmd-T)"); } - // 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 (clicks > 1) - fClickCount++; - else - fClickCount = 1; + virtual BSize MinSize() + { + return BSize(18, 12); } -} - -void -TabContainerView::MouseUp(BPoint where) -{ - fMouseDown = false; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { - fClickCount = 0; - fController->DoubleClickOutsideTabs(); + 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); } -} +}; -void -TabContainerView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - _MouseMoved(where, transit, dragMessage); -} - - -void -TabContainerView::DoLayout() -{ - BGroupView::DoLayout(); - - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons, false); - if (Bounds().Contains(where)) - _MouseMoved(where, B_INSIDE_VIEW, NULL); -} - -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(GroupLayout()->ItemAt(index - 1)); - if (item) - item->Parent()->SetIsLast(false); +class TabMenuTabButton : public TabButton { +public: + TabMenuTabButton(BMessage* message) + : TabButton(message) + { } -} -TabView* -TabContainerView::RemoveTab(int32 index) -{ - TabLayoutItem* item - = dynamic_cast(GroupLayout()->RemoveItem(index)); + virtual BSize MinSize() + { + return BSize(18, 12); + } - if (!item) - return NULL; + 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); + } +}; - BRect dirty(Bounds()); - dirty.left = item->Frame().left; - TabView* removedTab = item->Parent(); - removedTab->SetContainerView(NULL); - if (removedTab == fLastMouseEventTab) - fLastMouseEventTab = NULL; +enum { + MSG_SCROLL_TABS_LEFT = 'stlt', + MSG_SCROLL_TABS_RIGHT = 'strt' +}; - // Update tabs after or before the removed tab. - bool hasFrames = fController != NULL && fController->HasFrames(); - item = dynamic_cast(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(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); - } + +class TabContainerGroup : public BGroupView { +public: + TabContainerGroup(TabContainerView* tabContainerView) + : + BGroupView(B_HORIZONTAL), + fTabContainerView(tabContainerView), + fScrollLeftTabButton(NULL), + fScrollRightTabButton(NULL) + { + } + + virtual void AttachedToWindow() + { + if (fScrollLeftTabButton != NULL) + fScrollLeftTabButton->SetTarget(this); + if (fScrollRightTabButton != NULL) + fScrollRightTabButton->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; + default: + BGroupView::MessageReceived(message); + break; } } - Invalidate(dirty); - - return removedTab; -} - - -TabView* -TabContainerView::TabAt(int32 index) const -{ - TabLayoutItem* item = dynamic_cast( - 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( - 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()); - - fController->TabSelected(index); - } -} - - -void -TabContainerView::SetTabLabel(int32 tabIndex, const char* label) -{ - TabLayoutItem* item = dynamic_cast( - GroupLayout()->ItemAt(tabIndex)); - if (item == NULL) - return; - - item->Parent()->SetLabel(label); -} - - -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( - layout->ItemAt(i)); - if (item && item->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; + void AddScrollLeftButton(TabButton* button) + { + fScrollLeftTabButton = button; + GroupLayout()->AddView(button, 0.0f); } - if (fLastMouseEventTab && 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); + void AddScrollRightButton(TabButton* button) + { + fScrollRightTabButton = button; + GroupLayout()->AddView(button, 0.0f); } -} - -// #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 = 100.0f; - return size; -} - -BSize TabView::PreferredSize() -{ - return MaxSize(); -} - -BSize TabView::MaxSize() -{ - float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); - 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++; + void EnableScrollButtons(bool canScrollLeft, bool canScrollRight) + { + fScrollLeftTabButton->SetEnabled(canScrollLeft); + fScrollRightTabButton->SetEnabled(canScrollRight); + if (!canScrollLeft && !canScrollRight) { + // hide scroll buttons + } else { + // show scroll buttons + } } - 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); +private: + TabContainerView* fTabContainerView; + TabButton* fScrollLeftTabButton; + TabButton* fScrollRightTabButton; +}; + + +class TabButtonContainer : public BGroupView { +public: + TabButtonContainer() + : + BGroupView(B_HORIZONTAL) + { + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + GroupLayout()->SetInsets(0, 6, 0, 0); } -} -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; - BRect frame = fLayoutItem->Frame(); - frame.bottom++; - fContainerView->Invalidate(frame); -} - -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) -{ -} - -bool TabLayoutItem::IsVisible() -{ - return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); -} - -void TabLayoutItem::SetVisible(bool visible) -{ - // not allowed -} - -BRect TabLayoutItem::Frame() -{ - return fFrame; -} - -void TabLayoutItem::SetFrame(BRect frame) -{ - BRect dirty = fFrame; - fFrame = frame; - dirty = dirty | fFrame; - // Invalidate more than necessary, to help the TabContainerView - // redraw the parts outside any tabs... - dirty.bottom++; - dirty.right++; - fParent->ContainerView()->Invalidate(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; -} - - -// #pragma mark - TabManagerController + 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 { @@ -771,6 +301,12 @@ public: virtual void DoubleClickOutsideTabs(); + virtual void UpdateTabScrollability(bool canScrollLeft, + bool canScrollRight) + { + fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight); + } + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -786,11 +322,17 @@ public: void SetDoubleClickOutsideTabsMessage(const BMessage& message, const BMessenger& target); + void SetTabContainerGroup(TabContainerGroup* tabContainerGroup) + { + fTabContainerGroup = tabContainerGroup; + } + private: - TabManager* fManager; - bool fCloseButtonsAvailable; - BMessage* fDoubleClickOutsideTabsMessage; - BMessenger fTarget; + TabManager* fManager; + TabContainerGroup* fTabContainerGroup; + bool fCloseButtonsAvailable; + BMessage* fDoubleClickOutsideTabsMessage; + BMessenger fTarget; }; @@ -1021,6 +563,7 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, TabManagerController::TabManagerController(TabManager* manager) : fManager(manager), + fTabContainerGroup(NULL), fCloseButtonsAvailable(false), fDoubleClickOutsideTabsMessage(NULL) { @@ -1064,169 +607,6 @@ TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, } -// #pragma mark - TabButtonContainer - - -class TabButtonContainer : public BGroupView { -public: - TabButtonContainer() - : BGroupView(B_HORIZONTAL) - { - 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); - } -}; - - -// #pragma mark - TabButton - - -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, - flags, 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) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class ScrollRightTabButton : public TabButton { -public: - ScrollRightTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_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); - } -}; - - // #pragma mark - TabManager @@ -1243,9 +623,11 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fContainerView->SetLayout(fCardLayout); fTabContainerView = new TabContainerView(fController); - fTabContainerGroup = new BGroupView(B_HORIZONTAL); + 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"); @@ -1256,8 +638,10 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) #endif fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); + 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); diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/tabview/TabManager.h similarity index 97% rename from src/apps/webpositive/WebTabView.h rename to src/apps/webpositive/tabview/TabManager.h index 23ea4cc62f..04f86062a2 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -40,6 +40,7 @@ class BBitmap; class BCardLayout; class BGroupView; class BMenu; +class TabContainerGroup; class TabContainerView; class TabManagerController; @@ -81,7 +82,7 @@ private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; #endif - BGroupView* fTabContainerGroup; + TabContainerGroup* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; BCardLayout* fCardLayout; diff --git a/src/apps/webpositive/tabview/TabView.cpp b/src/apps/webpositive/tabview/TabView.cpp new file mode 100644 index 0000000000..bc5e2a6703 --- /dev/null +++ b/src/apps/webpositive/tabview/TabView.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 = 100.0f; + return size; +} + + +BSize +TabView::PreferredSize() +{ + return MaxSize(); +} + + +BSize +TabView::MaxSize() +{ + float extra = be_control_look->DefaultLabelSpacing(); + float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; + labelWidth = min_c(300.0f, labelWidth); + 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); +} diff --git a/src/apps/webpositive/tabview/TabView.h b/src/apps/webpositive/tabview/TabView.h new file mode 100644 index 0000000000..9f73c5a994 --- /dev/null +++ b/src/apps/webpositive/tabview/TabView.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include +#include + + +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 From a72e997ab0ab32f1afa97cd4378c4e8dc6b9f094 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 15 Apr 2010 15:35:52 +0000 Subject: [PATCH 169/293] Improved the design of the Go button graphics. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@417 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 80 +++++++++++++------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 57c1d8baa7..99072acc15 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -364,50 +364,50 @@ 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, 0xc0, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, 0xd5, 0xa6, 0xff, - 0x4a, 0x67, 0x50, 0xff, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0xb2, 0xf9, 0xc0, 0xff, 0x88, 0xbb, 0x91, 0xff, - 0x2e, 0x3d, 0x32, 0xff, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, - 0x73, 0xfa, 0x8c, 0xff, 0x9f, 0xf9, 0xae, 0xff, 0xac, 0xed, 0xb7, 0xff, 0x63, 0x96, 0x6d, 0xff, - 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0x5d, 0xfc, 0x7b, 0xff, 0x5d, 0xfc, 0x7b, 0xff, - 0x72, 0xf9, 0x88, 0xff, 0x6d, 0xe5, 0x82, 0xff, 0x50, 0xbf, 0x65, 0xff, 0x27, 0x63, 0x32, 0xff, - 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb4, 0xf8, 0xc0, 0xff, - 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfb, 0x76, 0xff, - 0x4a, 0xe8, 0x67, 0xff, 0x32, 0xcc, 0x50, 0xff, 0x27, 0x9e, 0x3d, 0xff, 0x15, 0x3d, 0x15, 0xff, - 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xa2, 0xf2, 0xb0, 0xff, 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xfa, 0x54, 0xff, - 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xf9, 0x54, 0xff, 0x27, 0xe4, 0x48, 0xff, 0x15, 0xc5, 0x38, 0xff, - 0x15, 0x98, 0x2e, 0xff, 0x00, 0x3b, 0x15, 0xff, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xe9, 0x99, 0xff, - 0x15, 0xf9, 0x40, 0xff, 0x15, 0xf9, 0x40, 0xff, 0x15, 0xed, 0x3d, 0xff, 0x00, 0xc8, 0x2b, 0xff, - 0x00, 0xa5, 0x22, 0xff, 0x00, 0x57, 0x15, 0xff, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x63, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x72, 0xe0, 0x86, 0xff, 0x22, 0xf5, 0x42, 0xff, 0x27, 0xda, 0x46, 0xff, - 0x15, 0xb6, 0x32, 0xff, 0x00, 0x74, 0x1c, 0xff, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x81, - 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x5f, 0xda, 0x76, 0xff, - 0x42, 0xd2, 0x5a, 0xff, 0x22, 0x95, 0x35, 0xff, 0x00, 0x2e, 0x00, 0xff, 0x00, 0x00, 0x00, 0xa2, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x46, 0xb6, 0x5c, 0xff, 0x1c, 0x54, 0x22, 0xff, 0x00, 0x00, 0x00, 0xc4, - 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xde, - 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 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 }; From 8421f16ef1d8c3d1c46ea9f185625aed11cca711 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 16 Apr 2010 12:22:35 +0000 Subject: [PATCH 170/293] Fix the build. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@418 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ac030f2f9d..3eedb566a7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -41,9 +41,9 @@ #include "NavMenu.h" #include "SettingsKeys.h" #include "SettingsMessage.h" +#include "TabManager.h" #include "URLInputGroup.h" #include "WebPage.h" -#include "WebTabView.h" #include "WebView.h" #include "WebViewConstants.h" #include From 3e2f25ae9f8a9f827673589d8f328952d86d3282 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 17 Apr 2010 22:48:37 +0000 Subject: [PATCH 171/293] Fixed Maxime's name in the About window. Really sorry about that! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@422 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index a32bbd04c0..a69cc84bea 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -88,7 +88,7 @@ void BrowserApp::AboutRequested() { BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " - "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus"); + "Maxime Simon, Michael Lotz, Rene Gollent and Stephan Aßmus"); aboutText << "\n\nSVN revision: " << kSVNRevision; BAlert* alert = new BAlert("About WebPositive", aboutText.String(), From 62c697303a515d2efdd95845291c52ab96cc9bb5 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 11:26:15 +0000 Subject: [PATCH 172/293] * Separated Text menu into Edit and View menus. * Added Cut/Copy/Paste items. Enabled status is updated when a text view has focus, but not yet with the selection of the BWebView, when that has focus. * Dispatch B_CUT/COPY/PASTE either to a focused BTextView or to the BWebView. * Enable the Find next/previous items according to contents of the Find text input. * Refactored MenusBeginning() hook. * Renamed Go menu to History. * Added Back/Forward menu items to History menu, now the shortcuts are visible. (Command key plus cursor left/right) * Added Reload item to View menu, now that shortcut is visible too. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@435 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 358 +++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 13 +- 2 files changed, 229 insertions(+), 142 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3eedb566a7..d937501291 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -90,10 +91,11 @@ enum { ZOOM_FACTOR_RESET = 'zfrs', ZOOM_TEXT_ONLY = 'zfto', - TEXT_SHOW_FIND_GROUP = 'sfnd', - TEXT_HIDE_FIND_GROUP = 'hfnd', - TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', SELECT_TAB = 'sltb', }; @@ -206,8 +208,26 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, quitItem->SetTarget(be_app); mainMenu->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu = new BMenu("Edit"); + menu->AddItem(fCutMenuItem = new BMenuItem("Cut", new BMessage(B_CUT), + 'X')); + menu->AddItem(fCopyMenuItem = new BMenuItem("Copy", new BMessage(B_COPY), + 'C')); + menu->AddItem(fPasteMenuItem = new BMenuItem("Paste", new BMessage(B_PASTE), + 'V')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Find", new BMessage(EDIT_SHOW_FIND_GROUP), + 'F')); + menu->AddItem(fFindPreviousMenuItem = new BMenuItem("Find previous", + new BMessage(EDIT_FIND_PREVIOUS), 'G', B_SHIFT_KEY)); + menu->AddItem(fFindNextMenuItem = new BMenuItem("Find next", + new BMessage(EDIT_FIND_NEXT), 'G')); + mainMenu->AddItem(menu); + fFindPreviousMenuItem->SetEnabled(false); + fFindNextMenuItem->SetEnabled(false); + + menu = new BMenu("View"); + menu->AddItem(new BMenuItem("Reload", new BMessage(RELOAD), 'R')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); @@ -218,8 +238,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, menu->AddItem(fZoomTextOnlyMenuItem); mainMenu->AddItem(menu); - fGoMenu = new BMenu("Go"); - mainMenu->AddItem(fGoMenu); + fHistoryMenu = new BMenu("History"); + fHistoryMenu->AddItem(new BMenuItem("Back", new BMessage(GO_BACK), B_LEFT_ARROW)); + fHistoryMenu->AddItem(new BMenuItem("Forward", new BMessage(GO_FORWARD), B_RIGHT_ARROW)); + fHistoryMenu->AddSeparatorItem(); + fHistoryMenuFixedItemCount = fHistoryMenu->CountItems(); + mainMenu->AddItem(fHistoryMenu); BPath bookmarkPath; entry_ref bookmarkRef; @@ -265,23 +289,26 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, const float kInsetSpacing = 3; const float kElementSpacing = 5; + // Find group fFindTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); + new BMessage(EDIT_FIND_NEXT)); + fFindTextControl->SetModificationMessage(new BMessage(FIND_TEXT_CHANGED)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(new BButton("Previous", new BMessage(EDIT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(EDIT_FIND_NEXT))) .Add(fFindCaseSensitiveCheckBox) .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .Add(new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP))) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) ; + // Navigation group BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) @@ -333,11 +360,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fNavigationGroup->SetVisible(false); } - AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); - AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); - AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); // Add shortcuts to select a particular tab for (int32 i = 0; i <= 9; i++) { @@ -534,24 +557,43 @@ BrowserWindow::MessageReceived(BMessage* message) // already zoomed. break; - case TEXT_FIND_NEXT: + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); break; - case TEXT_FIND_PREVIOUS: + case FIND_TEXT_CHANGED: + { + bool findTextAvailable = strlen(fFindTextControl->Text()) > 0; + fFindPreviousMenuItem->SetEnabled(findTextAvailable); + fFindNextMenuItem->SetEnabled(findTextAvailable); + break; + } + case EDIT_FIND_PREVIOUS: CurrentWebView()->FindString(fFindTextControl->Text(), false, fFindCaseSensitiveCheckBox->Value()); break; - case TEXT_SHOW_FIND_GROUP: + case EDIT_SHOW_FIND_GROUP: if (!fFindGroup->IsVisible()) fFindGroup->SetVisible(true); fFindTextControl->MakeFocus(true); break; - case TEXT_HIDE_FIND_GROUP: + case EDIT_HIDE_FIND_GROUP: if (fFindGroup->IsVisible()) fFindGroup->SetVisible(false); break; + case B_CUT: + case B_COPY: + case B_PASTE: + { + BTextView* textView = dynamic_cast(CurrentFocus()); + if (textView != NULL) + textView->MessageReceived(message); + else if (CurrentWebView() != NULL) + CurrentWebView()->MessageReceived(message); + break; + } + case SHOW_DOWNLOAD_WINDOW: case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); @@ -633,129 +675,11 @@ BrowserWindow::QuitRequested() } -static void -addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) -{ - BString baseURLLabel = baseURL(BString(newItem->Label())); - for (int32 i = menu->CountItems() - 1; i >= 0; i--) { - BMenuItem* item = menu->ItemAt(i); - BString label = item->Label(); - if (label.FindFirst(baseURLLabel) >= 0) { - if (item->Submenu()) { - // Submenu was already added in previous iteration. - item->Submenu()->AddItem(newItem); - return; - } else { - menu->RemoveItem(item); - BMenu* subMenu = new BMenu(baseURLLabel.String()); - subMenu->AddItem(item); - subMenu->AddItem(newItem); - // Add common submenu for this base URL, clickable. - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", baseURLLabel.String()); - menu->AddItem(new BMenuItem(subMenu, message), i); - return; - } - } - } - menu->AddItem(newItem); -} - - -static void -addOrDeleteMenu(BMenu* menu, BMenu* toMenu) -{ - if (menu->CountItems() > 0) - toMenu->AddItem(menu); - else - delete menu; -} - - void BrowserWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = fGoMenu->RemoveItem(0L))) - delete menuItem; - - BrowsingHistory* history = BrowsingHistory::DefaultInstance(); - if (!history->Lock()) - return; - - int32 count = history->CountItems(); - BMenuItem* clearHistoryItem = new BMenuItem("Clear history", - new BMessage(CLEAR_HISTORY)); - clearHistoryItem->SetEnabled(count > 0); - fGoMenu->AddItem(clearHistoryItem); - if (count == 0) { - history->Unlock(); - return; - } - fGoMenu->AddSeparatorItem(); - - BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); - todayStart.SetTime(BTime(0, 0, 0)); - - BDateTime oneDayAgoStart = todayStart; - oneDayAgoStart.Date().AddDays(-1); - - BDateTime twoDaysAgoStart = oneDayAgoStart; - twoDaysAgoStart.Date().AddDays(-1); - - BDateTime threeDaysAgoStart = twoDaysAgoStart; - threeDaysAgoStart.Date().AddDays(-1); - - BDateTime fourDaysAgoStart = threeDaysAgoStart; - fourDaysAgoStart.Date().AddDays(-1); - - BDateTime fiveDaysAgoStart = fourDaysAgoStart; - fiveDaysAgoStart.Date().AddDays(-1); - - BMenu* todayMenu = new BMenu("Today"); - BMenu* yesterdayMenu = new BMenu("Yesterday"); - BMenu* twoDaysAgoMenu = new BMenu( - twoDaysAgoStart.Date().LongDayName().String()); - BMenu* threeDaysAgoMenu = new BMenu( - threeDaysAgoStart.Date().LongDayName().String()); - BMenu* fourDaysAgoMenu = new BMenu( - fourDaysAgoStart.Date().LongDayName().String()); - BMenu* fiveDaysAgoMenu = new BMenu( - fiveDaysAgoStart.Date().LongDayName().String()); - BMenu* earlierMenu = new BMenu("Earlier"); - - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->HistoryItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.URL().String()); - - BString truncatedUrl(historyItem.URL()); - be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); - menuItem = new BMenuItem(truncatedUrl, message); - - if (historyItem.DateTime() < fiveDaysAgoStart) - addItemToMenuOrSubmenu(earlierMenu, menuItem); - else if (historyItem.DateTime() < fourDaysAgoStart) - addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < threeDaysAgoStart) - addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < twoDaysAgoStart) - addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < oneDayAgoStart) - addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < todayStart) - addItemToMenuOrSubmenu(yesterdayMenu, menuItem); - else - addItemToMenuOrSubmenu(todayMenu, menuItem); - } - history->Unlock(); - - addOrDeleteMenu(todayMenu, fGoMenu); - addOrDeleteMenu(yesterdayMenu, fGoMenu); - addOrDeleteMenu(twoDaysAgoMenu, fGoMenu); - addOrDeleteMenu(fourDaysAgoMenu, fGoMenu); - addOrDeleteMenu(fiveDaysAgoMenu, fGoMenu); - addOrDeleteMenu(earlierMenu, fGoMenu); + _UpdateHistoryMenu(); + _UpdateClipboardItems(); } @@ -1335,3 +1259,155 @@ BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, } +static void +addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) +{ + BString baseURLLabel = baseURL(BString(newItem->Label())); + for (int32 i = menu->CountItems() - 1; i >= 0; i--) { + BMenuItem* item = menu->ItemAt(i); + BString label = item->Label(); + if (label.FindFirst(baseURLLabel) >= 0) { + if (item->Submenu()) { + // Submenu was already added in previous iteration. + item->Submenu()->AddItem(newItem); + return; + } else { + menu->RemoveItem(item); + BMenu* subMenu = new BMenu(baseURLLabel.String()); + subMenu->AddItem(item); + subMenu->AddItem(newItem); + // Add common submenu for this base URL, clickable. + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", baseURLLabel.String()); + menu->AddItem(new BMenuItem(subMenu, message), i); + return; + } + } + } + menu->AddItem(newItem); +} + + +static void +addOrDeleteMenu(BMenu* menu, BMenu* toMenu) +{ + if (menu->CountItems() > 0) + toMenu->AddItem(menu); + else + delete menu; +} + + +void +BrowserWindow::_UpdateHistoryMenu() +{ + BMenuItem* menuItem; + while ((menuItem = fHistoryMenu->RemoveItem(fHistoryMenuFixedItemCount))) + delete menuItem; + + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (!history->Lock()) + return; + + int32 count = history->CountItems(); + BMenuItem* clearHistoryItem = new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY)); + clearHistoryItem->SetEnabled(count > 0); + fHistoryMenu->AddItem(clearHistoryItem); + if (count == 0) { + history->Unlock(); + return; + } + fHistoryMenu->AddSeparatorItem(); + + BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); + todayStart.SetTime(BTime(0, 0, 0)); + + BDateTime oneDayAgoStart = todayStart; + oneDayAgoStart.Date().AddDays(-1); + + BDateTime twoDaysAgoStart = oneDayAgoStart; + twoDaysAgoStart.Date().AddDays(-1); + + BDateTime threeDaysAgoStart = twoDaysAgoStart; + threeDaysAgoStart.Date().AddDays(-1); + + BDateTime fourDaysAgoStart = threeDaysAgoStart; + fourDaysAgoStart.Date().AddDays(-1); + + BDateTime fiveDaysAgoStart = fourDaysAgoStart; + fiveDaysAgoStart.Date().AddDays(-1); + + BMenu* todayMenu = new BMenu("Today"); + BMenu* yesterdayMenu = new BMenu("Yesterday"); + BMenu* twoDaysAgoMenu = new BMenu( + twoDaysAgoStart.Date().LongDayName().String()); + BMenu* threeDaysAgoMenu = new BMenu( + threeDaysAgoStart.Date().LongDayName().String()); + BMenu* fourDaysAgoMenu = new BMenu( + fourDaysAgoStart.Date().LongDayName().String()); + BMenu* fiveDaysAgoMenu = new BMenu( + fiveDaysAgoStart.Date().LongDayName().String()); + BMenu* earlierMenu = new BMenu("Earlier"); + + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->HistoryItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.URL().String()); + + BString truncatedUrl(historyItem.URL()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); + + if (historyItem.DateTime() < fiveDaysAgoStart) + addItemToMenuOrSubmenu(earlierMenu, menuItem); + else if (historyItem.DateTime() < fourDaysAgoStart) + addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < threeDaysAgoStart) + addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < twoDaysAgoStart) + addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < oneDayAgoStart) + addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < todayStart) + addItemToMenuOrSubmenu(yesterdayMenu, menuItem); + else + addItemToMenuOrSubmenu(todayMenu, menuItem); + } + history->Unlock(); + + addOrDeleteMenu(todayMenu, fHistoryMenu); + addOrDeleteMenu(yesterdayMenu, fHistoryMenu); + addOrDeleteMenu(twoDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(fourDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(fiveDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(earlierMenu, fHistoryMenu); +} + + +void +BrowserWindow::_UpdateClipboardItems() +{ + BTextView* focusTextView = dynamic_cast(CurrentFocus()); + if (focusTextView != NULL) { + int32 selectionStart; + int32 selectionEnd; + focusTextView->GetSelection(&selectionStart, &selectionEnd); + bool hasSelection = selectionStart < selectionEnd; + bool canPaste = false; + // A BTextView has the focus. + if (be_clipboard->Lock()) { + BMessage* data = be_clipboard->Data(); + if (data != NULL) + canPaste = data->HasData("text/plain", B_MIME_TYPE); + be_clipboard->Unlock(); + } + fCutMenuItem->SetEnabled(hasSelection); + fCopyMenuItem->SetEnabled(hasSelection); + fPasteMenuItem->SetEnabled(canPaste); + } else if (CurrentFocus() != CurrentWebView()) { + fCutMenuItem->SetEnabled(false); + fCopyMenuItem->SetEnabled(false); + fPasteMenuItem->SetEnabled(false); + } +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 124144cffb..03425cf43f 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -143,9 +143,20 @@ private: BMessage* message, uint32& addedCount) const; + void _UpdateHistoryMenu(); + void _UpdateClipboardItems(); + private: - BMenu* fGoMenu; + BMenu* fHistoryMenu; + int32 fHistoryMenuFixedItemCount; + + BMenuItem* fCutMenuItem; + BMenuItem* fCopyMenuItem; + BMenuItem* fPasteMenuItem; + BMenuItem* fFindPreviousMenuItem; + BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From 9b70fc27d27e13120c2d8566a020e8b124fd111e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 12:32:26 +0000 Subject: [PATCH 173/293] * Implemented a mechanism to ask the BWebPage about it's editing capabilities. This needs to be asynchronous, as always. BrowserWindow asks when menus are opened, but the result arrives so fast, that the user never sees invalid items. The Cut/Copy/Paste items are now always enabled according to what's currently really possible. * Enable and disable the Back/Forward History menu items along with the buttons. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@436 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 63 ++++++++++++++++++++++---- src/apps/webpositive/BrowserWindow.h | 3 ++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d937501291..e23bc229da 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -239,8 +239,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); - fHistoryMenu->AddItem(new BMenuItem("Back", new BMessage(GO_BACK), B_LEFT_ARROW)); - fHistoryMenu->AddItem(new BMenuItem("Forward", new BMessage(GO_FORWARD), B_RIGHT_ARROW)); + fHistoryMenu->AddItem(fBackMenuItem = new BMenuItem("Back", + new BMessage(GO_BACK), B_LEFT_ARROW)); + fHistoryMenu->AddItem(fForwardMenuItem = new BMenuItem("Forward", + new BMessage(GO_FORWARD), B_RIGHT_ARROW)); fHistoryMenu->AddSeparatorItem(); fHistoryMenuFixedItemCount = fHistoryMenu->CountItems(); mainMenu->AddItem(fHistoryMenu); @@ -594,6 +596,29 @@ BrowserWindow::MessageReceived(BMessage* message) break; } + case B_EDITING_CAPABILITIES_RESULT: + { + BWebView* webView; + if (message->FindPointer("view", + reinterpret_cast(&webView)) != B_OK + || webView != CurrentWebView()) { + break; + } + bool canCut; + bool canCopy; + bool canPaste; + if (message->FindBool("can cut", &canCut) != B_OK) + canCut = false; + if (message->FindBool("can copy", &canCopy) != B_OK) + canCopy = false; + if (message->FindBool("can paste", &canPaste) != B_OK) + canPaste = false; + fCutMenuItem->SetEnabled(canCut); + fCopyMenuItem->SetEnabled(canCopy); + fPasteMenuItem->SetEnabled(canPaste); + break; + } + case SHOW_DOWNLOAD_WINDOW: case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); @@ -683,6 +708,19 @@ BrowserWindow::MenusBeginning() } +void +BrowserWindow::MenusEnded() +{ + // Reenabled the clipboard items, since we don't update them when + // the capabilities really change, but only when the menu is opened. + // The shortcuts need to work when the capabilities change without + // the Edit menu being opened meanwhile. + fCutMenuItem->SetEnabled(true); + fCopyMenuItem->SetEnabled(true); + fPasteMenuItem->SetEnabled(true); +} + + void BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { @@ -957,12 +995,12 @@ BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, if (view != CurrentWebView()) return; - if (fBackButton) - fBackButton->SetEnabled(canGoBackward); - if (fForwardButton) - fForwardButton->SetEnabled(canGoForward); - if (fStopButton) - fStopButton->SetEnabled(canStop); + fBackButton->SetEnabled(canGoBackward); + fForwardButton->SetEnabled(canGoForward); + fStopButton->SetEnabled(canStop); + + fBackMenuItem->SetEnabled(canGoBackward); + fForwardMenuItem->SetEnabled(canGoForward); } @@ -1405,9 +1443,16 @@ BrowserWindow::_UpdateClipboardItems() fCutMenuItem->SetEnabled(hasSelection); fCopyMenuItem->SetEnabled(hasSelection); fPasteMenuItem->SetEnabled(canPaste); - } else if (CurrentFocus() != CurrentWebView()) { + } else if (CurrentWebView() != NULL) { + // Trigger update of the clipboard items, even if the + // BWebView doesn't have focus, we'll dispatch these message + // there anyway. This works so fast that the user can never see + // the wrong enabled state when the menu opens until the result + // message arrives. fCutMenuItem->SetEnabled(false); fCopyMenuItem->SetEnabled(false); fPasteMenuItem->SetEnabled(false); + + CurrentWebView()->WebPage()->SendEditingCapabilities(); } } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 03425cf43f..0eda3126dd 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -81,6 +81,7 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); + virtual void MenusEnded(); void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); @@ -156,6 +157,8 @@ private: BMenuItem* fFindPreviousMenuItem; BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + BMenuItem* fBackMenuItem; + BMenuItem* fForwardMenuItem; IconButton* fBackButton; IconButton* fForwardButton; From ae82400bb4ff73fbc67c1d618ebf7fb53d1d83e3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:43:23 +0000 Subject: [PATCH 174/293] The return key is never supposed to reach the BTextView implementation, even if we don't have to invoke in the URLTextView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@440 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 99072acc15..b372fcfbdc 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -269,6 +269,10 @@ URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes) SelectAll(); break; + case B_RETURN: + // Don't let this through to the text view. + break; + default: BTextView::KeyDown(bytes, numBytes); break; From a150602b0f1b17573d179f8b63e85f3467a8068d Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:44:10 +0000 Subject: [PATCH 175/293] Return early in BrowserWindow::DispatchMessage(), if the message was already handled. This would also fix return keys ending up in the URLTextView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@441 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e23bc229da..8ed76b199d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -397,11 +397,13 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { modifiers = modifiers & 0x000000ff; - if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) + if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_BACK); - else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) + return; + } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); - else if (target == fURLInputGroup->TextView()) { + return; + } else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there @@ -413,6 +415,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) fURLInputGroup->GoButton()->Invoke(); snooze(1000); fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); + return; } } } From d5e2e814a417ed7606dcfd6c480c4db844f8acf9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:46:23 +0000 Subject: [PATCH 176/293] No need to block the BApplication thread when showing the About window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@442 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index a69cc84bea..86bdfb1a75 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -93,7 +93,7 @@ BrowserApp::AboutRequested() BAlert* alert = new BAlert("About WebPositive", aboutText.String(), "Sweet!"); - alert->Go(); + alert->Go(NULL); } From 0e7170b49e6cfc864ea0f711485549b8bfcafb5c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 16:24:16 +0000 Subject: [PATCH 177/293] Handling shortcut is wrappedd inside MenusBeginning() and MenusEnded(), so we need to always enable the standard shortcut items in MenusBeginning(), if we would otherwise enable them only asynchronously. Fixes Cut/Copy/Paste via shortcuts. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@443 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8ed76b199d..acffde3387 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1452,9 +1452,9 @@ BrowserWindow::_UpdateClipboardItems() // there anyway. This works so fast that the user can never see // the wrong enabled state when the menu opens until the result // message arrives. - fCutMenuItem->SetEnabled(false); - fCopyMenuItem->SetEnabled(false); - fPasteMenuItem->SetEnabled(false); + fCutMenuItem->SetEnabled(true); + fCopyMenuItem->SetEnabled(true); + fPasteMenuItem->SetEnabled(true); CurrentWebView()->WebPage()->SendEditingCapabilities(); } From c53bbc329d7e8a58eba8ec3edaf017c54334332e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 16:26:32 +0000 Subject: [PATCH 178/293] Implementing MenusEnded() is not needed anymore, since we enable Cut/Copy/Paste by default now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@444 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++-------------- src/apps/webpositive/BrowserWindow.h | 1 - 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index acffde3387..784d4a2f6a 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -711,19 +711,6 @@ BrowserWindow::MenusBeginning() } -void -BrowserWindow::MenusEnded() -{ - // Reenabled the clipboard items, since we don't update them when - // the capabilities really change, but only when the menu is opened. - // The shortcuts need to work when the capabilities change without - // the Edit menu being opened meanwhile. - fCutMenuItem->SetEnabled(true); - fCopyMenuItem->SetEnabled(true); - fPasteMenuItem->SetEnabled(true); -} - - void BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { @@ -1451,7 +1438,10 @@ BrowserWindow::_UpdateClipboardItems() // BWebView doesn't have focus, we'll dispatch these message // there anyway. This works so fast that the user can never see // the wrong enabled state when the menu opens until the result - // message arrives. + // message arrives. The initial state needs to be enabled, since + // standard shortcut handling is always wrapped inside MenusBeginning() + // and MenusEnded(), and since we update items asynchronously, we need + // to have them enabled to begin with. fCutMenuItem->SetEnabled(true); fCopyMenuItem->SetEnabled(true); fPasteMenuItem->SetEnabled(true); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0eda3126dd..73b6fdd48c 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -81,7 +81,6 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); - virtual void MenusEnded(); void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); From 9d150599741158a2e9efd09305020a73b5d0bd8f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 22:52:41 +0000 Subject: [PATCH 179/293] Make the base URL show in bold font in the URL input field, and the rest of the text in dark gray. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@445 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index b372fcfbdc..c1f9c999b9 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -171,6 +171,7 @@ URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) fPreviousText("") { MakeResizable(true); + SetStylable(true); } @@ -334,6 +335,31 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, 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); + } } From 25057e59b7e5914185854eda2e33bc1fe49c6a31 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 21 Apr 2010 11:49:28 +0000 Subject: [PATCH 180/293] When selecting choices in the auto-completion pop-up, insert the current choice into the text view, so the user can continue typing from that choice, or modify it. For example, one can type "dev.haiku-os.org", select a choice "http://dev.haiku-os.org/ticket/1234" and then replace just the last chunk with another ticket number and press enter. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@447 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 5ae515b529..9f0a90b065 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -94,9 +94,15 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) 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_ESCAPE: CancelChoice(); From fa485bda233dbf3fc885816b6b0f4e95fe034ab7 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 21:01:42 +0000 Subject: [PATCH 181/293] When removing the currently selected tab, temporarily unset the current BWebView, since we did not delete the BWebView directly, but in the application thread, this was a race condition that would only crash sometimes (in _TabChanged(), when we tried to attach user data to the current tab before switching it). This should fix the last known (to me) crash. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@452 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 784d4a2f6a..cd13d89309 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -694,7 +694,7 @@ BrowserWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. while (fTabManager->CountTabs() > 0) _ShutdownTab(0); - SetCurrentWebView(0); + SetCurrentWebView(NULL); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -1056,6 +1056,8 @@ BrowserWindow::_ShutdownTab(int32 index) { BView* view = fTabManager->RemoveTab(index); BWebView* webView = dynamic_cast(view); + if (webView == CurrentWebView()) + SetCurrentWebView(NULL); if (webView != NULL) webView->Shutdown(); else From 88b25a7da970e034e24ec8f7fb7ad232344f7872 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 21:22:06 +0000 Subject: [PATCH 182/293] Add a small hack to fix the invalidation glitches in the menu bar when resizing the window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@453 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index cd13d89309..a3a4043495 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -342,6 +342,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(statusGroup) ); + // TODO: Small hack for fixing some invalidation problems with BMenuBar... + mainMenu->SetFlags(mainMenu->Flags() | B_FULL_UPDATE_ON_RESIZE); + mainMenu->SetViewColor(B_TRANSPARENT_COLOR); + fURLInputGroup->MakeFocus(true); fMenuGroup = layoutItemFor(mainMenu); From f7530134b1b87dc483f6d62309433ce4e22188fe Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 22:19:41 +0000 Subject: [PATCH 183/293] Don't set the text if it's the same, allows to keep selection. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@454 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index c1f9c999b9..6fb51e498c 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -603,7 +603,8 @@ URLInputGroup::TextView() const void URLInputGroup::SetText(const char* text) { - fTextView->SetText(text); + if (!text || !Text() || strcmp(Text(), text) != 0) + fTextView->SetText(text); } From a8d1c85daab2129c69f4f91131f543460cc80d20 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 15:02:17 +0000 Subject: [PATCH 184/293] Fixed looking up uint32 values. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@455 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/SettingsMessage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index e11900b1b5..15dc12394c 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -363,10 +363,10 @@ SettingsMessage::GetValue(const char* name, int32 defaultValue) const uint32 SettingsMessage::GetValue(const char* name, uint32 defaultValue) const { - int32 value; - if (FindInt32(name, &value) != B_OK) + uint32 value; + if (FindUInt32(name, &value) != B_OK) return defaultValue; - return (uint32)value; + return value; } From 1547f92b8ea875c3a0c15f4c78fd473720ec95d0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 15:07:53 +0000 Subject: [PATCH 185/293] * Improved the layout of the Settings window general page. * Allow specifying a start and a search page in the Settings window. * Separated the "New page" policy into "New window" and "New tab" policies. For a new window, the user can chose to "Open start page", "Open search page" and "Open blank page". The default changed to "Open start page" and the default start page points to the "Welcome" readme. For new tabs, there is an additional choice "Clone current page". The default stayed with opening a blank page. * Implemented the new page policies in BrowserWindow. * Listen for changes of the new settings in BrowserWindow. * Added the new settings keys and default values to SettingsKeys. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@456 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 52 ++++++- src/apps/webpositive/BrowserWindow.h | 12 ++ src/apps/webpositive/SettingsKeys.cpp | 12 ++ src/apps/webpositive/SettingsKeys.h | 8 ++ src/apps/webpositive/SettingsWindow.cpp | 177 +++++++++++++++++++----- src/apps/webpositive/SettingsWindow.h | 21 ++- 6 files changed, 236 insertions(+), 46 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a3a4043495..f4d0e58a4c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -166,11 +166,22 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true) { + // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); // fZoomTextOnly = fAppSettings->GetValue("zoom text only", fZoomTextOnly); fShowTabsIfSinglePageOpen = fAppSettings->GetValue( kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + fNewWindowPolicy = fAppSettings->GetValue(kSettingsKeyNewWindowPolicy, + (uint32)OpenStartPage); + fNewTabPolicy = fAppSettings->GetValue(kSettingsKeyNewTabPolicy, + (uint32)OpenBlankPage); + fStartPageURL = fAppSettings->GetValue(kSettingsKeyStartPageURL, + kDefaultStartPageURL); + fSearchPageURL = fAppSettings->GetValue(kSettingsKeySearchPageURL, + kDefaultSearchPageURL); + + // Create the interface elements BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); @@ -672,12 +683,26 @@ BrowserWindow::MessageReceived(BMessage* message) if (message->FindString("name", &name) != B_OK) break; bool flag; + BString string; + uint32 value; if (name == kSettingsKeyShowTabsIfSinglePageOpen && message->FindBool("value", &flag) == B_OK) { if (fShowTabsIfSinglePageOpen != flag) { fShowTabsIfSinglePageOpen = flag; _UpdateTabGroupVisibility(); } + } else if (name == kSettingsKeyStartPageURL + && message->FindString("value", &string) == B_OK) { + fStartPageURL = string; + } else if (name == kSettingsKeySearchPageURL + && message->FindString("value", &string) == B_OK) { + fSearchPageURL = string; + } else if (name == kSettingsKeyNewWindowPolicy + && message->FindUInt32("value", &value) == B_OK) { + fNewWindowPolicy = value; + } else if (name == kSettingsKeyNewTabPolicy + && message->FindUInt32("value", &value) == B_OK) { + fNewTabPolicy = value; } break; } @@ -716,15 +741,38 @@ BrowserWindow::MenusBeginning() void -BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) +BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { // Executed in app thread (new BWebPage needs to be created in app thread). if (!webView) webView = new BWebView("web view"); + bool isNewWindow = fTabManager->CountTabs() == 0; + fTabManager->AddTab(webView, "New tab"); - if (url.Length()) + BString url(_url); + if (url.Length() == 0) { + uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; + // Implement new page policy + switch (policy) { + case OpenStartPage: + url = fStartPageURL; + break; + case OpenSearchPage: + url = fSearchPageURL; + break; + case CloneCurrentPage: + if (CurrentWebView() != NULL) + url = CurrentWebView()->MainFrameURL(); + break; + default: + case OpenBlankPage: + break; + } + } + + if (url.Length() > 0) webView->LoadURL(url.String()); if (select) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 73b6fdd48c..31886fa045 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -56,6 +56,13 @@ enum ToolbarPolicy { DoNotHaveToolbar }; +enum NewPagePolicy { + OpenBlankPage = 0, + OpenStartPage = 1, + OpenSearchPage = 2, + CloneCurrentPage = 3 +}; + enum { NEW_WINDOW = 'nwnd', NEW_TAB = 'ntab', @@ -176,9 +183,14 @@ private: BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; + uint32 fNewWindowPolicy; + uint32 fNewTabPolicy; + BString fStartPageURL; + BString fSearchPageURL; }; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 7fe0c4e1e2..5df66469ca 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -30,3 +30,15 @@ const char* kSettingsKeyDownloadPath = "download path"; const char* kSettingsKeyShowTabsIfSinglePageOpen = "show tabs if single page open"; + +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/system/documentation/welcome/welcome_en.html"; +const char* kDefaultSearchPageURL = "http://www.google.com"; + diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 584a320e86..112e903e81 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -33,5 +33,13 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; +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; #endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8591fd8c6a..c24b0b1d0a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -48,6 +48,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" +#include "BrowserWindow.h" #include "FontSelectionView.h" #include "SettingsKeys.h" #include "SettingsMessage.h" @@ -63,9 +64,12 @@ enum { MSG_REVERT = 'rvrt', MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_START_PAGE_CHANGED = 'hpch', + MSG_SEARCH_PAGE_CHANGED = 'spch', MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', - MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', - MSG_GO_MENU_DAYS_CHANGED = 'digm', + MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc', + MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', + MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', }; @@ -209,61 +213,94 @@ SettingsWindow::Show() BView* SettingsWindow::_CreateGeneralPage(float spacing) { + fStartPageControl = new BTextControl("start page", + TR("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); + fStartPageControl->SetText( + fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); + + fSearchPageControl = new BTextControl("search page", + TR("Search page:"), "", new BMessage(MSG_SEARCH_PAGE_CHANGED)); + fSearchPageControl->SetText( + fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); + fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); fDownloadFolderControl->SetText( - fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); - fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + fNewWindowBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); - fNewPageBehaviorCloneCurrentItem->SetEnabled(false); - fNewPageBehaviorOpenHomeItem = new BMenuItem(TR("Open home page"), NULL); - fNewPageBehaviorOpenHomeItem->SetEnabled(false); - fNewPageBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fNewPageBehaviorOpenSearchItem->SetEnabled(false); - fNewPageBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fNewPageBehaviorOpenBlankItem->SetMarked(true); - BPopUpMenu* newPageBehaviorMenu = new BPopUpMenu("New pages"); - newPageBehaviorMenu->AddItem(fNewPageBehaviorCloneCurrentItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenHomeItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenSearchItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenBlankItem); - fNewPageBehaviorMenu = new BMenuField("new page behavior", - TR("New pages:"), newPageBehaviorMenu, - new BMessage(MSG_NEW_PAGE_BEHAVIOR_CHANGED)); -fNewPageBehaviorMenu->SetEnabled(false); + fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + NULL); + fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); + fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fDaysInGoMenuControl = new BTextControl("days in go menu", - TR("Number of days to keep links in Go menu:"), "", - new BMessage(MSG_GO_MENU_DAYS_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", + TR("New windows:"), newWindowBehaviorMenu, + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); + + BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenHomeItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); + fNewTabBehaviorMenu = new BMenuField("new tab behavior", + TR("New tabs:"), newTabBehaviorMenu, + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + + fDaysInHistoryMenuControl = new BTextControl("days in history", + TR("Number of days to keep links in History menu:"), "", + new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); BString maxHistoryAge; maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); - fDaysInGoMenuControl->SetText(maxHistoryAge.String()); + fDaysInHistoryMenuControl->SetText(maxHistoryAge.String()); for (uchar i = 0; i < '0'; i++) - fDaysInGoMenuControl->TextView()->DisallowChar(i); + fDaysInHistoryMenuControl->TextView()->DisallowChar(i); for (uchar i = '9' + 1; i <= 128; i++) - fDaysInGoMenuControl->TextView()->DisallowChar(i); + fDaysInHistoryMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", TR("Show tabs if only one page is open."), new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); - BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) - .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) - .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) + .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) + .Add(fStartPageControl->CreateTextViewLayoutItem(), 1, 0) - .Add(fNewPageBehaviorMenu->CreateLabelLayoutItem(), 0, 2) - .Add(fNewPageBehaviorMenu->CreateMenuBarLayoutItem(), 1, 2) + .Add(fSearchPageControl->CreateLabelLayoutItem(), 0, 1) + .Add(fSearchPageControl->CreateTextViewLayoutItem(), 1, 1) - .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) - .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) + .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 2) + .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 2) - .Add(fShowTabsIfOnlyOnePage, 0, 4, 2) + .Add(fNewWindowBehaviorMenu->CreateLabelLayoutItem(), 0, 3) + .Add(fNewWindowBehaviorMenu->CreateMenuBarLayoutItem(), 1, 3) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) + .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(fDaysInHistoryMenuControl) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) ; @@ -330,20 +367,42 @@ void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); if (maxHistoryAge <= 0) maxHistoryAge = 1; if (maxHistoryAge >= 35) maxHistoryAge = 35; BString text; text << maxHistoryAge; - fDaysInGoMenuControl->SetText(text.String()); + 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); + // New window policy + uint32 newWindowPolicy = OpenStartPage; + BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewWindowBehaviorOpenSearchItem) + newWindowPolicy = OpenSearchPage; + else if (markedItem == fNewWindowBehaviorOpenBlankItem) + newWindowPolicy = OpenBlankPage; + fSettings->SetValue(kSettingsKeyNewWindowPolicy, newWindowPolicy); + + // New tab policy + uint32 newTabPolicy = OpenBlankPage; + markedItem = fNewTabBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewTabBehaviorCloneCurrentItem) + newTabPolicy = CloneCurrentPage; + else if (markedItem == fNewTabBehaviorOpenHomeItem) + newTabPolicy = OpenStartPage; + else if (markedItem == fNewTabBehaviorOpenSearchItem) + newTabPolicy = OpenSearchPage; + fSettings->SetValue(kSettingsKeyNewTabPolicy, newTabPolicy); + // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); fSettings->SetValue("serif font", fSerifFontView->Font()); @@ -373,11 +432,53 @@ SettingsWindow::_ApplySettings() void SettingsWindow::_RevertSettings() { + fStartPageControl->SetText( + fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); + + fSearchPageControl->SetText( + fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); + fDownloadFolderControl->SetText( - fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + // 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", diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 1e9d7e3421..1824471541 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -67,13 +67,22 @@ private: private: SettingsMessage* fSettings; + BTextControl* fStartPageControl; + BTextControl* fSearchPageControl; BTextControl* fDownloadFolderControl; - BMenuField* fNewPageBehaviorMenu; - BMenuItem* fNewPageBehaviorCloneCurrentItem; - BMenuItem* fNewPageBehaviorOpenHomeItem; - BMenuItem* fNewPageBehaviorOpenSearchItem; - BMenuItem* fNewPageBehaviorOpenBlankItem; - BTextControl* fDaysInGoMenuControl; + + BMenuField* fNewWindowBehaviorMenu; + BMenuItem* fNewWindowBehaviorOpenHomeItem; + BMenuItem* fNewWindowBehaviorOpenSearchItem; + BMenuItem* fNewWindowBehaviorOpenBlankItem; + + BMenuField* fNewTabBehaviorMenu; + BMenuItem* fNewTabBehaviorCloneCurrentItem; + BMenuItem* fNewTabBehaviorOpenHomeItem; + BMenuItem* fNewTabBehaviorOpenSearchItem; + BMenuItem* fNewTabBehaviorOpenBlankItem; + + BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; FontSelectionView* fStandardFontView; From b0240c4936c561e4e964f35663f1b7344110ac42 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 16:07:22 +0000 Subject: [PATCH 186/293] Allow setting a listener target and a modification message. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@457 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/FontSelectionView.cpp | 36 ++++++++++++++++++- .../webpositive/support/FontSelectionView.h | 8 +++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 24fcd248fb..c463a8c9ef 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,9 @@ static const int32 kMsgSetSize = 'size'; FontSelectionView::FontSelectionView(const char* name, const char* label, bool separateStyles, const BFont* currentFont) : - BHandler(name) + BHandler(name), + fMessage(NULL), + fTarget(NULL) { if (currentFont == NULL) fCurrentFont = _DefaultFont(); @@ -96,6 +99,8 @@ FontSelectionView::~FontSelectionView() delete fStylesMenuField; if (!fFontsMenuField->Window()) delete fFontsMenuField; + + delete fMessage; } @@ -120,6 +125,7 @@ FontSelectionView::MessageReceived(BMessage* message) fCurrentFont.SetSize(size); _UpdateFontPreview(); + _Invoke(); break; } @@ -153,6 +159,8 @@ FontSelectionView::MessageReceived(BMessage* message) if (fStylesMenuField != NULL) _AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu()); } + + _Invoke(); break; } @@ -173,6 +181,7 @@ FontSelectionView::MessageReceived(BMessage* message) fCurrentFont.SetFamilyAndStyle(family, style); _UpdateFontPreview(); + _Invoke(); break; } @@ -182,6 +191,21 @@ FontSelectionView::MessageReceived(BMessage* message) } +void +FontSelectionView::SetMessage(BMessage* message) +{ + delete fMessage; + fMessage = message; +} + + +void +FontSelectionView::SetTarget(BHandler* target) +{ + fTarget = target; +} + + // #pragma mark - @@ -379,6 +403,16 @@ FontSelectionView::PreviewBox() const // #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 { diff --git a/src/apps/webpositive/support/FontSelectionView.h b/src/apps/webpositive/support/FontSelectionView.h index f25801a840..8ee630b448 100644 --- a/src/apps/webpositive/support/FontSelectionView.h +++ b/src/apps/webpositive/support/FontSelectionView.h @@ -35,6 +35,9 @@ public: 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); @@ -59,6 +62,8 @@ public: BView* PreviewBox() const; private: + void _Invoke(); + BFont _DefaultFont() const; void _SelectCurrentFont(bool select); void _SelectCurrentSize(bool select); @@ -78,6 +83,9 @@ protected: BFont fSavedFont; BFont fCurrentFont; + + BMessage* fMessage; + BHandler* fTarget; }; #endif // FONT_SELECTION_VIEW_H From b1957a61f69eec02dbd2636f4cdb94aa5869445c Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 16:09:04 +0000 Subject: [PATCH 187/293] * The current max history age was not read from the BrowsingHistory in SettingsWindow::_RevertSettings(). * Made all necessary refactoring in order to support _CanApplySettings(). * Adjust the Apply and Revert button enabled state whenever settings change. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@458 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 270 ++++++++++++++++++------ src/apps/webpositive/SettingsWindow.h | 19 +- 2 files changed, 219 insertions(+), 70 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index c24b0b1d0a..c5a5577800 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -62,8 +62,7 @@ enum { MSG_APPLY = 'aply', MSG_CANCEL = 'cncl', MSG_REVERT = 'rvrt', - MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', - MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_START_PAGE_CHANGED = 'hpch', MSG_SEARCH_PAGE_CHANGED = 'spch', MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', @@ -71,6 +70,14 @@ enum { MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', + + 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', }; static const int32 kDefaultFontSize = 14; @@ -106,17 +113,14 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) tabView->AddTab(_CreateGeneralPage(spacing)); tabView->AddTab(_CreateFontsPage(spacing)); - AddHandler(fStandardFontView); - fStandardFontView->AttachedToLooper(); - - AddHandler(fSerifFontView); - fSerifFontView->AttachedToLooper(); - - AddHandler(fSansSerifFontView); - fSansSerifFontView->AttachedToLooper(); - - AddHandler(fFixedFontView); - fFixedFontView->AttachedToLooper(); + _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); @@ -168,17 +172,30 @@ SettingsWindow::MessageReceived(BMessage* message) fStandardFontView->SetSize(size); fSerifFontView->SetSize(size); fSansSerifFontView->SetSize(size); + _ValidateButtonsEnabled(); break; } case MSG_FIXED_FONT_SIZE_SELECTED: { int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); fFixedFontView->SetSize(size); + _ValidateButtonsEnabled(); 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_STANDARD_FONT_CHANGED: + case MSG_SERIF_FONT_CHANGED: + case MSG_SANS_SERIF_FONT_CHANGED: + case MSG_FIXED_FONT_CHANGED: // TODO: Some settings could change live, some others not? + _ValidateButtonsEnabled(); break; default: @@ -215,32 +232,40 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fStartPageControl = new BTextControl("start page", TR("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", TR("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", TR("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(TR("Open start page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), - NULL); - fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), - NULL); - fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenHomeItem->SetMarked(true); fNewTabBehaviorOpenBlankItem->SetMarked(true); @@ -250,8 +275,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem); newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem); fNewWindowBehaviorMenu = new BMenuField("new window behavior", - TR("New windows:"), newWindowBehaviorMenu, - new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); + TR("New windows:"), newWindowBehaviorMenu); BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); @@ -259,12 +283,13 @@ SettingsWindow::_CreateGeneralPage(float spacing) newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); fNewTabBehaviorMenu = new BMenuField("new tab behavior", - TR("New tabs:"), newTabBehaviorMenu, - new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + TR("New tabs:"), newTabBehaviorMenu); fDaysInHistoryMenuControl = new BTextControl("days in history", TR("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()); @@ -363,15 +388,109 @@ SettingsWindow::_CreateFontsPage(float spacing) } +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 || (_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)); + + return canApply; +} + + void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); - if (maxHistoryAge <= 0) - maxHistoryAge = 1; - if (maxHistoryAge >= 35) - maxHistoryAge = 35; + int32 maxHistoryAge = _MaxHistoryAge(); BString text; text << maxHistoryAge; fDaysInHistoryMenuControl->SetText(text.String()); @@ -383,25 +502,9 @@ SettingsWindow::_ApplySettings() fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); - // New window policy - uint32 newWindowPolicy = OpenStartPage; - BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked(); - if (markedItem == fNewWindowBehaviorOpenSearchItem) - newWindowPolicy = OpenSearchPage; - else if (markedItem == fNewWindowBehaviorOpenBlankItem) - newWindowPolicy = OpenBlankPage; - fSettings->SetValue(kSettingsKeyNewWindowPolicy, newWindowPolicy); - - // New tab policy - uint32 newTabPolicy = OpenBlankPage; - markedItem = fNewTabBehaviorMenu->Menu()->FindMarked(); - if (markedItem == fNewTabBehaviorCloneCurrentItem) - newTabPolicy = CloneCurrentPage; - else if (markedItem == fNewTabBehaviorOpenHomeItem) - newTabPolicy = OpenStartPage; - else if (markedItem == fNewTabBehaviorOpenSearchItem) - newTabPolicy = OpenSearchPage; - fSettings->SetValue(kSettingsKeyNewTabPolicy, newTabPolicy); + // New page policies + fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); + fSettings->SetValue(kSettingsKeyNewTabPolicy, _NewTabPolicy()); // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); @@ -426,6 +529,9 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); + + + _ValidateButtonsEnabled(); } @@ -443,6 +549,10 @@ SettingsWindow::_RevertSettings() fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + BString text; + text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); + fDaysInHistoryMenuControl->SetText(text.String()); + // New window policy uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy, (uint32)OpenStartPage); @@ -495,33 +605,63 @@ SettingsWindow::_RevertSettings() *be_plain_font), defaultFontSize); fFixedFontView->SetFont(fSettings->GetValue("fixed font", *be_fixed_font), defaultFixedFontSize); + + _ValidateButtonsEnabled(); } void -SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat) +SettingsWindow::_ValidateButtonsEnabled() { - const float kMinSize = 8.0; - const float kMaxSize = 18.0; + 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); +} - 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; +// #pragma mark - - char label[32]; - snprintf(label, sizeof(label), "%ld", size); - BMessage* message = new BMessage(messageWhat); - message->AddInt32("size", size); +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; +} - BMenuItem* item = new BMenuItem(label, message); - menu->AddItem(item); - item->SetTarget(this); - } +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; } @@ -541,7 +681,7 @@ SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value) int32 -SettingsWindow::_SizesMenuValue(BMenu* menu) +SettingsWindow::_SizesMenuValue(BMenu* menu) const { if (BMenuItem* item = menu->FindMarked()) { if (BMessage* message = item->Message()) { diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 1824471541..a3b6417ec9 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -53,14 +53,23 @@ public: private: BView* _CreateGeneralPage(float spacing); BView* _CreateFontsPage(float spacing); - - void _ApplySettings(); - void _RevertSettings(); - void _BuildSizesMenu(BMenu* menu, uint32 messageWhat); + void _SetupFontSelectionView( + FontSelectionView* view, + BMessage* message); + + bool _CanApplySettings() const; + void _ApplySettings(); + void _RevertSettings(); + void _ValidateButtonsEnabled(); + + uint32 _NewWindowPolicy() const; + uint32 _NewTabPolicy() const; + int32 _MaxHistoryAge() const; + void _SetSizesMenuValue(BMenu* menu, int32 value); - int32 _SizesMenuValue(BMenu* menu); + int32 _SizesMenuValue(BMenu* menu) const; BFont _FindDefaultSerifFont() const; From 3cba4f1616fda0ea8c8b6890b086799d00df7525 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 17:00:08 +0000 Subject: [PATCH 188/293] Optimize default window size for 1024x768. Actually I would like to optimize for 800x600 by default, but then the Welcome page opens with horizontal scroll bar. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@459 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 86bdfb1a75..e9976d0c5d 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -62,7 +62,7 @@ BrowserApp::BrowserApp() : BApplication(kApplicationSignature), fWindowCount(0), - fLastWindowFrame(100, 100, 700, 750), + fLastWindowFrame(50, 50, 950, 750), fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), From a0fcf3c05ee1c8e410fca75868ead94aa99682f1 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 24 Apr 2010 00:46:24 +0000 Subject: [PATCH 189/293] Never apply the new page policy if we already have the BWebView. If we already have it, it was created by the ChromeClient and navigation is soon going to happen with it. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@460 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f4d0e58a4c..8b0a15d526 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -743,8 +743,9 @@ BrowserWindow::MenusBeginning() void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { + bool applyNewPagePolicy = webView == NULL; // Executed in app thread (new BWebPage needs to be created in app thread). - if (!webView) + if (webView == NULL) webView = new BWebView("web view"); bool isNewWindow = fTabManager->CountTabs() == 0; @@ -752,7 +753,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->AddTab(webView, "New tab"); BString url(_url); - if (url.Length() == 0) { + if (applyNewPagePolicy && url.Length() == 0) { uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; // Implement new page policy switch (policy) { From 54cc547050faded7e2b9918cf0c8839360add704 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 25 Apr 2010 13:45:05 +0000 Subject: [PATCH 190/293] Make sure a filename derived from a bookmark title does not contain invalid characters for a filename. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@461 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8b0a15d526..e5988d1833 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1193,6 +1193,9 @@ BrowserWindow::_CreateBookmark() if (leafPos >= 0) bookmarkName.Remove(0, leafPos + 1); } + // Make sure the bookmark title does not contain chars that are not + // allowed in file names. + bookmarkName.ReplaceAll('/', '-'); // Check that the bookmark exists nowhere in the bookmark hierarchy, // though the intended file name must match, we don't search the stored From 34da9596562803b4d8369f0cf41948d638d3fdb7 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Apr 2010 15:13:57 +0000 Subject: [PATCH 191/293] Cleanup the supported types. Claiming support for image/jpeg, gif and png is not really useful. Neither is claiming support for text/*. Added support for image/svg+xml, since I don't think anything else would handle it as good as WebPositive (which will do better once BView supports affine transformations). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@462 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 5734330206..1079ab970a 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -14,11 +14,8 @@ resource app_flags B_SINGLE_LAUNCH; resource file_types message { "types" = "text/html", - "types" = "image/gif", - "types" = "image/jpeg", - "types" = "image/png", + "types" = "image/svg+xml", "types" = "application/x-vnd.Be-bookmark", - "types" = "text", "types" = "application/x-vnd.Be-doc_bookmark", "types" = "application/x-vnd.Be.URL.file", "types" = "application/x-vnd.Be.URL.ftp", From 969b9a9669b105cb809c1d2315800160204519bb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Apr 2010 15:44:32 +0000 Subject: [PATCH 192/293] Give focus back to the web view when hiding the Find controls. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@463 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e5988d1833..552b2ee885 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -598,8 +598,11 @@ BrowserWindow::MessageReceived(BMessage* message) fFindTextControl->MakeFocus(true); break; case EDIT_HIDE_FIND_GROUP: - if (fFindGroup->IsVisible()) + if (fFindGroup->IsVisible()) { fFindGroup->SetVisible(false); + if (CurrentWebView() != NULL) + CurrentWebView()->MakeFocus(true); + } break; case B_CUT: From 50c66f38576be9af6e806361871107f51405de1a Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 14:05:35 +0000 Subject: [PATCH 193/293] * Store the favicon in the PageUserData of any BWebView instance. * Refactored setting the page icon so it always goes through the new BrowserWindow::_SetPageIcon(). * Don't replace the PageUserData in _TabChanged() if it already exists (which would forget the favicon). * Write the favicon to the Bookmark file. At the moment, it writes the 32x32 icon as upscaled version of the 16x16 icon. Color reduction makes the icons look not so nice, since Haiku does not yet support PNG icons... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@464 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 112 +++++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 3 + 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 552b2ee885..9699ca2bd7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -139,17 +139,43 @@ class PageUserData : public BWebView::UserData { public: PageUserData(BView* focusedView) : - fFocusedView(focusedView) + fFocusedView(focusedView), + fPageIcon(NULL) { } + ~PageUserData() + { + delete fPageIcon; + } + + void SetFocusedView(BView* focusedView) + { + fFocusedView = focusedView; + } + BView* FocusedView() const { return fFocusedView; } + void SetPageIcon(const BBitmap* icon) + { + delete fPageIcon; + if (icon) + fPageIcon = new BBitmap(icon); + else + fPageIcon = NULL; + } + + const BBitmap* PageIcon() const + { + return fPageIcon; + } + private: - BView* fFocusedView; + BView* fFocusedView; + BBitmap* fPageIcon; }; @@ -456,7 +482,7 @@ BrowserWindow::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) url = fURLInputGroup->Text(); - fTabManager->SetTabIcon(CurrentWebView(), NULL); + _SetPageIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; } @@ -1019,7 +1045,7 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { - fTabManager->SetTabIcon(view, icon); + _SetPageIcon(view, icon); } @@ -1128,14 +1154,24 @@ BrowserWindow::_TabChanged(int32 index) if (webView == CurrentWebView()) return; - if (CurrentWebView() != NULL) - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (CurrentWebView() != NULL) { + // Remember the currently focused view before switching tabs, + // so that we can revert the focus when switching back to this tab + // later. + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData) + userData->SetFocusedView(CurrentFocus()); + else + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + } SetCurrentWebView(webView); if (webView != NULL) { _UpdateTitle(webView->MainFrameTitle()); + // Restore the previous focus or focus the web view. PageUserData* userData = static_cast( webView->GetUserData()); if (userData != NULL && userData->FocusedView() != NULL) @@ -1247,8 +1283,53 @@ BrowserWindow::_CreateBookmark() } BNodeInfo nodeInfo(&bookmarkFile); - if (status == B_OK) + if (status == B_OK) { status = nodeInfo.SetType("application/x-vnd.Be-bookmark"); + if (status == B_OK) { + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData != NULL && userData->PageIcon() != NULL) { + BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, + B_CMAP8); + status_t ret = miniIcon.ImportBits(userData->PageIcon()); + if (ret == B_OK) + ret = nodeInfo.SetIcon(&miniIcon, B_MINI_ICON); + if (ret != B_OK) { + fprintf(stderr, "Failed to store mini icon for bookmark: " + "%s\n", strerror(ret)); + } + BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, + B_CMAP8); + // TODO: Store 32x32 favicon which is often provided by sites. + const uint8* src = (const uint8*)miniIcon.Bits(); + uint32 srcBPR = miniIcon.BytesPerRow(); + uint8* dst = (uint8*)largeIcon.Bits(); + uint32 dstBPR = largeIcon.BytesPerRow(); + for (uint32 y = 0; y < 16; y++) { + const uint8* s = src; + uint8* d = dst; + for (uint32 x = 0; x < 16; x++) { + *d++ = *s; + *d++ = *s++; + } + dst += dstBPR; + s = src; + for (uint32 x = 0; x < 16; x++) { + *d++ = *s; + *d++ = *s++; + } + dst += dstBPR; + src += srcBPR; + } + if (ret == B_OK) + ret = nodeInfo.SetIcon(&largeIcon, B_LARGE_ICON); + if (ret != B_OK) { + fprintf(stderr, "Failed to store large icon for bookmark: " + "%s\n", strerror(ret)); + } + } + } + } if (status != B_OK) { BString message("There was an error creating the bookmark " @@ -1348,6 +1429,23 @@ BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, } +void +BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon) +{ + PageUserData* userData = static_cast(view->GetUserData()); + if (userData == NULL) { + userData = new(std::nothrow) PageUserData(NULL); + if (userData == NULL) + return; + view->SetUserData(userData); + } + // The PageUserData makes a copy of the icon, which we pass on to + // the TabManager for display in the respective tab. + userData->SetPageIcon(icon); + fTabManager->SetTabIcon(view, userData->PageIcon()); +} + + static void addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 31886fa045..9f3937257b 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -150,6 +150,9 @@ private: BMessage* message, uint32& addedCount) const; + void _SetPageIcon(BWebView* view, + const BBitmap* icon); + void _UpdateHistoryMenu(); void _UpdateClipboardItems(); From 65cc5e49ee22e22dae9204db37a33ab636f39bf3 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 15:08:05 +0000 Subject: [PATCH 194/293] The favicon is now also displayed in the URL input view. Mostly because one is used to it, but also when only one page is open and tabs are not displayed as per the user settings, the favicon would then not be visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@465 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++- src/apps/webpositive/URLInputGroup.cpp | 94 ++++++++++++++++++++++++-- src/apps/webpositive/URLInputGroup.h | 4 ++ 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9699ca2bd7..c5f9ce96e4 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1174,8 +1174,14 @@ BrowserWindow::_TabChanged(int32 index) // Restore the previous focus or focus the web view. PageUserData* userData = static_cast( webView->GetUserData()); - if (userData != NULL && userData->FocusedView() != NULL) - userData->FocusedView()->MakeFocus(true); + BView* focusedView = NULL; + if (userData != NULL) { + focusedView = userData->FocusedView(); + fURLInputGroup->SetPageIcon(userData->PageIcon()); + } + + if (focusedView != NULL) + focusedView->MakeFocus(true); else webView->MakeFocus(true); @@ -1443,6 +1449,8 @@ BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon) // the TabManager for display in the respective tab. userData->SetPageIcon(icon); fTabManager->SetTabIcon(view, userData->PageIcon()); + if (view == CurrentWebView()) + fURLInputGroup->SetPageIcon(icon); } diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 6fb51e498c..4e252855b3 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -128,7 +128,7 @@ private: // #pragma mark - URLTextView -static const float kHorizontalTextRectInset = 3.0; +static const float kHorizontalTextRectInset = 4.0; class URLInputGroup::URLTextView : public BTextView { @@ -505,9 +505,14 @@ public: SetHighColor(0, 0, 0, 120); } - BPoint bitmapLocation(kFrameInset, kFrameInset); - if (Value() == B_CONTROL_ON) - bitmapLocation += BPoint(1, 1); + if (fBitmap == NULL) + return; + 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); } @@ -517,6 +522,76 @@ private: }; +// #pragma mark - IconView + + +class URLInputGroup::PageIconView : public BView { +public: + PageIconView() + : + BView("page icon view", B_WILL_DRAW), + fIcon(NULL) + { + SetDrawingMode(B_OP_OVER); + } + + ~PageIconView() + { + delete fIcon; + } + + virtual void Draw(BRect updateRect) + { + if (fIcon == NULL) + return; + + BRect bounds(Bounds()); + BRect iconBounds(fIcon->Bounds()); + BPoint iconPos( + 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, iconPos); + } + + virtual BSize MinSize() + { + if (fIcon != NULL) { + return BSize(fIcon->Bounds().Width() + 3, + fIcon->Bounds().Height() + 3); + } + 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; + delete fIcon; + if (icon) + fIcon = new BBitmap(icon); + else + fIcon = NULL; + Invalidate(); + InvalidateLayout(); + } + +private: + BBitmap* fIcon; +}; + + // #pragma mark - URLInputGroup @@ -527,6 +602,9 @@ URLInputGroup::URLInputGroup(BMessage* goMessage) { GroupLayout()->SetInsets(2, 2, 2, 2); + fIconView = new PageIconView(); + GroupLayout()->AddView(fIconView, 0.0f); + fTextView = new URLTextView(this); AddChild(fTextView); @@ -537,7 +615,7 @@ URLInputGroup::URLInputGroup(BMessage* goMessage) // fGoButton = new BitmapButton("kActionGo", NULL); fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth, kGoBitmapHeight, kGoBitmapFormat, goMessage); - GroupLayout()->AddView(fGoButton, 0.0); + GroupLayout()->AddView(fGoButton, 0.0f); SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); SetLowColor(ViewColor()); @@ -622,3 +700,9 @@ URLInputGroup::GoButton() const } +void +URLInputGroup::SetPageIcon(const BBitmap* icon) +{ + fIconView->SetIcon(icon); +} + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h index 105b76d932..d71f713ca7 100644 --- a/src/apps/webpositive/URLInputGroup.h +++ b/src/apps/webpositive/URLInputGroup.h @@ -27,9 +27,13 @@ public: BButton* GoButton() const; + void SetPageIcon(const BBitmap* icon); + private: + class PageIconView; class URLTextView; + PageIconView* fIconView; URLTextView* fTextView; BButton* fGoButton; bool fWindowActive; From a4c1f6783dbe0ebd25a5699c648a26794574c9e0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 15:40:36 +0000 Subject: [PATCH 195/293] * After a recent commit, _TabChanged() was accessing "webView" when it really meant CurrentWebView(). This also fixed the focus restoration, since it remembered the current focus for the wrong web view when the user data was already stored. * Refactored _TabChanged() so that this code is now executed in the now virtual SetCurrentWebView(), which makes the features also work for new tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@466 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 107 +++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 2 + 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c5f9ce96e4..d1ee857392 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -750,9 +750,9 @@ BrowserWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. + SetCurrentWebView(NULL); while (fTabManager->CountTabs() > 0) _ShutdownTab(0); - SetCurrentWebView(NULL); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -769,6 +769,69 @@ BrowserWindow::MenusBeginning() } +static bool +viewIsChild(const BView* parent, const BView* view) +{ + if (parent == view) + return true; + + int32 count = parent->CountChildren(); + for (int32 i = 0; i < count; i++) { + BView* child = parent->ChildAt(i); + if (viewIsChild(child, view)) + return true; + } + return false; +} + + +void +BrowserWindow::SetCurrentWebView(BWebView* webView) +{ + if (webView == CurrentWebView()) + return; + + if (CurrentWebView() != NULL) { + // Remember the currently focused view before switching tabs, + // so that we can revert the focus when switching back to this tab + // later. + PageUserData* userData = static_cast( + CurrentWebView()->GetUserData()); + if (userData) + userData->SetFocusedView(CurrentFocus()); + else + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + } + + BWebWindow::SetCurrentWebView(webView); + + if (webView != NULL) { + _UpdateTitle(webView->MainFrameTitle()); + + // Restore the previous focus or focus the web view. + PageUserData* userData = static_cast( + webView->GetUserData()); + BView* focusedView = NULL; + if (userData != NULL) { + focusedView = userData->FocusedView(); + fURLInputGroup->SetPageIcon(userData->PageIcon()); + } + + if (focusedView != NULL + && viewIsChild(GetLayout()->View(), focusedView)) { + focusedView->MakeFocus(true); + } else + webView->MakeFocus(true); + + fURLInputGroup->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } else + _UpdateTitle(""); +} + + void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { @@ -1150,47 +1213,7 @@ BrowserWindow::_ShutdownTab(int32 index) void BrowserWindow::_TabChanged(int32 index) { - BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - return; - - if (CurrentWebView() != NULL) { - // Remember the currently focused view before switching tabs, - // so that we can revert the focus when switching back to this tab - // later. - PageUserData* userData = static_cast( - webView->GetUserData()); - if (userData) - userData->SetFocusedView(CurrentFocus()); - else - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); - } - - SetCurrentWebView(webView); - - if (webView != NULL) { - _UpdateTitle(webView->MainFrameTitle()); - - // Restore the previous focus or focus the web view. - PageUserData* userData = static_cast( - webView->GetUserData()); - BView* focusedView = NULL; - if (userData != NULL) { - focusedView = userData->FocusedView(); - fURLInputGroup->SetPageIcon(userData->PageIcon()); - } - - if (focusedView != NULL) - focusedView->MakeFocus(true); - else - webView->MakeFocus(true); - - fURLInputGroup->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } else - _UpdateTitle(""); + SetCurrentWebView(dynamic_cast(fTabManager->ViewForTab(index))); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9f3937257b..0e2769db49 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -89,6 +89,8 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); + virtual void SetCurrentWebView(BWebView* view); + void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); From 5913d4a98b5c55e91bb9327e89d748747e439ffd Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 16:33:17 +0000 Subject: [PATCH 196/293] * Invalidate layout only when necessary. * Icon view needs to update completely on resize. -> Fixes graphics glitch when switching between icon and no icon. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@467 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 4e252855b3..40805943fc 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -529,7 +529,7 @@ class URLInputGroup::PageIconView : public BView { public: PageIconView() : - BView("page icon view", B_WILL_DRAW), + BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fIcon(NULL) { SetDrawingMode(B_OP_OVER); @@ -578,13 +578,14 @@ public: { if (icon == NULL && fIcon == NULL) return; + if (!(fIcon != NULL && icon != NULL)) + InvalidateLayout(); delete fIcon; if (icon) fIcon = new BBitmap(icon); else fIcon = NULL; Invalidate(); - InvalidateLayout(); } private: From 99006ca0ae2b9ef0e9d33ce69bf97894c6e86f3d Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 17:49:21 +0000 Subject: [PATCH 197/293] * Added page for proxy server configuration to the Settings window. * Added necessary wiring in BWebSettings for proxy server configuration. Actual proxy server usage untested, feedback welcome. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@468 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsKeys.cpp | 3 + src/apps/webpositive/SettingsKeys.h | 4 + src/apps/webpositive/SettingsWindow.cpp | 112 ++++++++++++++++++++++-- src/apps/webpositive/SettingsWindow.h | 9 +- 4 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 5df66469ca..d525ba6aeb 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -42,3 +42,6 @@ const char* kDefaultStartPageURL = "file:///boot/system/documentation/welcome/welcome_en.html"; 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"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 112e903e81..6be0e5e15c 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -42,4 +42,8 @@ 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 diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index c5a5577800..b9fa66136a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -78,6 +78,10 @@ enum { 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; @@ -112,6 +116,7 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) tabView->AddTab(_CreateGeneralPage(spacing)); tabView->AddTab(_CreateFontsPage(spacing)); + tabView->AddTab(_CreateProxyPage(spacing)); _SetupFontSelectionView(fStandardFontView, new BMessage(MSG_STANDARD_FONT_CHANGED)); @@ -172,14 +177,14 @@ SettingsWindow::MessageReceived(BMessage* message) fStandardFontView->SetSize(size); fSerifFontView->SetSize(size); fSansSerifFontView->SetSize(size); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; } case MSG_FIXED_FONT_SIZE_SELECTED: { int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); fFixedFontView->SetSize(size); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; } @@ -194,8 +199,11 @@ SettingsWindow::MessageReceived(BMessage* message) 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? - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; default: @@ -329,7 +337,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName("General"); + view->SetName(TR("General")); return view; } @@ -383,7 +391,48 @@ SettingsWindow::_CreateFontsPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName("Fonts"); + view->SetName(TR("Fonts")); + return view; +} + + +BView* +SettingsWindow::_CreateProxyPage(float spacing) +{ + fUseProxyCheckBox = new BCheckBox("use proxy", + TR("Use proxy server to connect to the internet."), + new BMessage(MSG_USE_PROXY_CHANGED)); + fUseProxyCheckBox->SetValue(B_CONTROL_ON); + + fProxyAddressControl = new BTextControl("proxy address", + TR("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", + TR("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) + ; + view->SetName(TR("Proxy server")); return view; } @@ -482,6 +531,16 @@ SettingsWindow::_CanApplySettings() const 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; } @@ -516,6 +575,15 @@ SettingsWindow::_ApplySettings() 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. @@ -526,12 +594,18 @@ SettingsWindow::_ApplySettings() 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(); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); } @@ -606,12 +680,21 @@ SettingsWindow::_RevertSettings() fFixedFontView->SetFont(fSettings->GetValue("fixed font", *be_fixed_font), defaultFixedFontSize); - _ValidateButtonsEnabled(); + // 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::_ValidateButtonsEnabled() +SettingsWindow::_ValidateControlsEnabledStatus() { bool canApply = _CanApplySettings(); fApplyButton->SetEnabled(canApply); @@ -619,6 +702,10 @@ SettingsWindow::_ValidateButtonsEnabled() // 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); } @@ -714,3 +801,12 @@ SettingsWindow::_FindDefaultSerifFont() const } return serifFont; } + + +uint32 +SettingsWindow::_ProxyPort() const +{ + return atoul(fProxyPortControl->Text()); +} + + diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index a3b6417ec9..c595632f8e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -53,6 +53,7 @@ public: private: BView* _CreateGeneralPage(float spacing); BView* _CreateFontsPage(float spacing); + BView* _CreateProxyPage(float spacing); void _BuildSizesMenu(BMenu* menu, uint32 messageWhat); void _SetupFontSelectionView( @@ -62,7 +63,7 @@ private: bool _CanApplySettings() const; void _ApplySettings(); void _RevertSettings(); - void _ValidateButtonsEnabled(); + void _ValidateControlsEnabledStatus(); uint32 _NewWindowPolicy() const; uint32 _NewTabPolicy() const; @@ -73,6 +74,8 @@ private: BFont _FindDefaultSerifFont() const; + uint32 _ProxyPort() const; + private: SettingsMessage* fSettings; @@ -99,6 +102,10 @@ private: FontSelectionView* fSansSerifFontView; FontSelectionView* fFixedFontView; + BCheckBox* fUseProxyCheckBox; + BTextControl* fProxyAddressControl; + BTextControl* fProxyPortControl; + BButton* fApplyButton; BButton* fCancelButton; BButton* fRevertButton; From 464aca712fec2d1d0db5200721e5acc0529e6a0b Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 1 May 2010 18:07:40 +0000 Subject: [PATCH 198/293] Fix a bug with closing tabs by pressing the tertiary mouse button. fMouseDown would be true, but the fLastMouseEventTab would have been reset when removing the tab. Rather than fixing this problem, behave the same as Firefox and close the tab on mouse up (when the mouse is still over the tab, which allows the user a way back out). Avoids the above problem as a side effect. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@469 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 2 +- src/apps/webpositive/tabview/TabManager.cpp | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index a4c26ddb2d..6f502b2850 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -440,7 +440,7 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, return; } - if (fLastMouseEventTab && fLastMouseEventTab == tab) + if (fLastMouseEventTab != NULL && fLastMouseEventTab == tab) fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); else { if (fLastMouseEventTab) diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 814496e582..bdde273b04 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -366,6 +366,7 @@ private: TabManagerController* fController; bool fOverCloseRect; bool fClicked; + bool fCloseOnMouseUp; }; @@ -375,7 +376,8 @@ WebTabView::WebTabView(TabManagerController* controller) fIcon(NULL), fController(controller), fOverCloseRect(false), - fClicked(false) + fClicked(false), + fCloseOnMouseUp(false) { } @@ -449,7 +451,7 @@ void WebTabView::MouseDown(BPoint where, uint32 buttons) { if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); + fCloseOnMouseUp = true; return; } @@ -467,12 +469,20 @@ WebTabView::MouseDown(BPoint where, uint32 buttons) void WebTabView::MouseUp(BPoint where) { - if (!fClicked) { + 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)); From 06ea485752153d9dd4bd8d02e617b28758dd7229 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 1 May 2010 19:20:53 +0000 Subject: [PATCH 199/293] Add a context menu to the download progress view. It allows to open the containing folder (and selects the file in it), and to copy the download URL to the clipboard. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@470 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 112 +++++++++++++++++- src/apps/webpositive/DownloadProgressView.h | 2 + 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index ddee6317c5..54ca1797e6 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -32,12 +32,15 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include #include @@ -49,10 +52,12 @@ enum { - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', + 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; @@ -203,6 +208,10 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) bool DownloadProgressView::Init(BMessage* archive) { + // We need to receive mouse events even for the areas of children views, + // so we can pop up a context menu. + SetEventMask(B_POINTER_EVENTS); + fCurrentSize = 0; fExpectedSize = 0; fLastUpdateTime = 0; @@ -330,6 +339,35 @@ DownloadProgressView::AllAttached() } +void +DownloadProgressView::MouseDown(BPoint where) +{ + if (!Bounds().Contains(where)) + return; + + int32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) + return; + + if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) + return; + + where = ConvertToScreen(where) + 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(where, true, true, true); +} + + void DownloadProgressView::Draw(BRect updateRect) { @@ -477,6 +515,71 @@ DownloadProgressView::MessageReceived(BMessage* message) } 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); } @@ -534,6 +637,7 @@ DownloadProgressView::DownloadCanceled() fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); fInfoView->SetText(""); + fPath.Unset(); } diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index 4c4ae7e48f..256245442d 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -57,6 +57,8 @@ public: virtual void DetachedFromWindow(); virtual void AllAttached(); + virtual void MouseDown(BPoint where); + virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); From ef4f1b553391ba664a1ef6a287b1afc6039f4f61 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 11:02:05 +0000 Subject: [PATCH 200/293] Since fLastMouseEventTab is never updated in _MouseMoved() while fMouseDown is true, we need to recheck it in MouseUp(). This would fix the problem with the middle mouse button click to close tabs if we didn't move closing to the mouse up event, and it also fixes other situations, like clicking on one tab, moving the mouse over another tab's close button, releasing the mouse and clicking again without moving it inbetween. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@471 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 6f502b2850..70badaf3d1 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -151,9 +151,16 @@ TabContainerView::MouseUp(BPoint where) if (fLastMouseEventTab) fLastMouseEventTab->MouseUp(where); 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. fClickCount = 0; fController->DoubleClickOutsideTabs(); } + // Always check the tab under the mouse again, since we don't update + // it with fMouseDown == true. + _SendFakeMouseMoved(); } From b9d4b634f6406790a909a0a1c4a3770e3d8620fb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 11:45:22 +0000 Subject: [PATCH 201/293] Use BStatusBar properly. The text in a BStatusBar is composed of four parts. Label and trailing label are only specified in the constructor or in Reset(). By using SetText(), we were modifying another part of the text, while we meant to set the label. This fixes updates on node monitor messages. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@472 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 54ca1797e6..e7914e8736 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -501,7 +501,9 @@ DownloadProgressView::MessageReceived(BMessage* message) } } - fStatusBar->SetText(name); + float value = fStatusBar->CurrentValue(); + fStatusBar->Reset(name); + fStatusBar->SetTo(value); Window()->PostMessage(SAVE_SETTINGS); break; } From d5c4471790572a33a47d80317f523aac096c216e Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 12:20:37 +0000 Subject: [PATCH 202/293] * Fixed double click outside tabs to only be recognized when the first click was outside as well. * Single tertiary click outside tabs opens new tab on mouse up. * Reset fClickCount always when the click was inside a tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@474 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 70badaf3d1..fc0f41b8bc 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -136,8 +136,11 @@ TabContainerView::MouseDown(BPoint where) if (fLastMouseEventTab) fLastMouseEventTab->MouseDown(where, buttons); else { - if (clicks > 1) - fClickCount++; + 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; } @@ -148,15 +151,16 @@ void TabContainerView::MouseUp(BPoint where) { fMouseDown = false; - if (fLastMouseEventTab) + if (fLastMouseEventTab) { fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { + 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. - fClickCount = 0; fController->DoubleClickOutsideTabs(); + fClickCount = 0; } // Always check the tab under the mouse again, since we don't update // it with fMouseDown == true. From 1a2246ccf975d3f45c6ee4e9606ca80b843be60d Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 13:09:54 +0000 Subject: [PATCH 203/293] Avoid loading the start page before loading the requested URL in new windows by passing the url to the constructor already. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@476 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 8 ++++---- src/apps/webpositive/BrowserWindow.cpp | 6 +++--- src/apps/webpositive/BrowserWindow.h | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index e9976d0c5d..b6f1cc349e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -169,7 +169,8 @@ BrowserApp::ReadyToRun() fLaunchRefsMessage = 0; } if (pagesCreated == 0) { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, + ""); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -347,10 +348,9 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, + url); window->Show(); - if (url.Length()) - window->CurrentWebView()->LoadURL(url.String()); } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d1ee857392..d1835a7544 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -183,7 +183,7 @@ private: BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, - ToolbarPolicy toolbarPolicy, BWebView* webView) + const BString& url, ToolbarPolicy toolbarPolicy, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, @@ -391,7 +391,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindGroup = layoutItemFor(findGroup); fStatusGroup = layoutItemFor(statusGroup); - CreateNewTab("", true, webView); + CreateNewTab(url, true, webView); fFindGroup->SetVisible(false); @@ -911,7 +911,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, - DoNotHaveToolbar, view); + BString(), DoNotHaveToolbar, view); window->Show(); } else CreateNewTab(BString(), activate, view); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0e2769db49..1dd2951410 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -79,6 +79,7 @@ class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, SettingsMessage* appSettings, + const BString& url, ToolbarPolicy = HaveToolbar, BWebView* webView = NULL); virtual ~BrowserWindow(); From ea992272d768de9784c9154976fe984d1d408f94 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 16:52:02 +0000 Subject: [PATCH 204/293] Added a few utility classes from Haiku. To be removed when WebPositive moves into Haiku. Added new file HashKeys.h which implements commonly used HashKey classes. Additionally to the ones found in HashMap.h, it has a HashKeyString class, which wraps a BString and provides the GetHashCode() method. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@477 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/AutoLocker.h | 178 +++++++ src/apps/webpositive/support/HashKeys.h | 124 +++++ src/apps/webpositive/support/HashMap.h | 481 +++++++++++++++++ src/apps/webpositive/support/HashSet.h | 342 ++++++++++++ src/apps/webpositive/support/OpenHashTable.h | 514 +++++++++++++++++++ 5 files changed, 1639 insertions(+) create mode 100644 src/apps/webpositive/support/AutoLocker.h create mode 100644 src/apps/webpositive/support/HashKeys.h create mode 100644 src/apps/webpositive/support/HashMap.h create mode 100644 src/apps/webpositive/support/HashSet.h create mode 100644 src/apps/webpositive/support/OpenHashTable.h diff --git a/src/apps/webpositive/support/AutoLocker.h b/src/apps/webpositive/support/AutoLocker.h new file mode 100644 index 0000000000..9baa7aa7a5 --- /dev/null +++ b/src/apps/webpositive/support/AutoLocker.h @@ -0,0 +1,178 @@ +/* + * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _AUTO_LOCKER_H +#define _AUTO_LOCKER_H + + +#include + + +namespace BPrivate { + +// AutoLockerStandardLocking +template +class AutoLockerStandardLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->Lock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->Unlock(); + } +}; + +// AutoLockerReadLocking +template +class AutoLockerReadLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->ReadLock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->ReadUnlock(); + } +}; + +// AutoLockerWriteLocking +template +class AutoLockerWriteLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->WriteLock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->WriteUnlock(); + } +}; + +// AutoLocker +template > +class AutoLocker { +private: + typedef AutoLocker 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& operator=(Lockable* lockable) + { + SetTo(lockable); + return *this; + } + + inline AutoLocker& 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 diff --git a/src/apps/webpositive/support/HashKeys.h b/src/apps/webpositive/support/HashKeys.h new file mode 100644 index 0000000000..3480b56492 --- /dev/null +++ b/src/apps/webpositive/support/HashKeys.h @@ -0,0 +1,124 @@ +/* + * Copyright 2010, Stephan Aßmus . All rights reserved. + * Copyright 2004-2007, Ingo Weinhold . All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef HASH_KEYS_H +#define HASH_KEYS_H + +#include + + +namespace BPrivate { + +#if 0 +// TODO: Move here from HashMap.h and adapt all clients. +// HashKey32 +template +struct HashKey32 { + HashKey32() {} + HashKey32(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + return (uint32)value; + } + + HashKey32 operator=(const HashKey32& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey32& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey32& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashKey64 +template +struct HashKey64 { + HashKey64() {} + HashKey64(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + uint64 v = (uint64)value; + return (uint32)(v >> 32) ^ (uint32)v; + } + + HashKey64 operator=(const HashKey64& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey64& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey64& 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 diff --git a/src/apps/webpositive/support/HashMap.h b/src/apps/webpositive/support/HashMap.h new file mode 100644 index 0000000000..36b321f2b8 --- /dev/null +++ b/src/apps/webpositive/support/HashMap.h @@ -0,0 +1,481 @@ +// HashMap.h +// +// Copyright (c) 2004-2007, Ingo Weinhold (bonefish@cs.tu-berlin.de) +// +// 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 + +#include "AutoLocker.h" +#include "OpenHashTable.h" + + +namespace BPrivate { + +// HashMapElement +template +class HashMapElement : public OpenHashElement { +private: + typedef HashMapElement 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(_element); + return (fKey == element.fKey); + } + + inline void Adopt(Element &element) + { + fKey = element.fKey; + fValue = element.fValue; + } + + Key fKey; + Value fValue; +}; + +// HashMap +template +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 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* map) + : + fMap(const_cast*>(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; + + HashMap* 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 Element; + friend class Iterator; + +private: + Element *_FindElement(const Key& key) const; + +protected: + OpenHashElementArray fElementArray; + OpenHashTable > fTable; +}; + +// SynchronizedHashMap +template +class SynchronizedHashMap : public BLocker { +public: + typedef struct HashMap::Entry Entry; + typedef struct HashMap::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(lock)); + if (!locker.IsLocked()) + return Value(); + return fMap.Get(key); + } + + bool ContainsKey(const Key& key) const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + if (!locker.IsLocked()) + return false; + return fMap.ContainsKey(key); + } + + int32 Size() const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + return fMap.Size(); + } + + Iterator GetIterator() + { + return fMap.GetIterator(); + } + + // for debugging only + const HashMap& GetUnsynchronizedMap() const { return fMap; } + HashMap& GetUnsynchronizedMap() { return fMap; } + +protected: + typedef AutoLocker MapLocker; + + HashMap fMap; +}; + +// HashKey32 +template +struct HashKey32 { + HashKey32() {} + HashKey32(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + return (uint32)value; + } + + HashKey32 operator=(const HashKey32& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey32& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey32& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashKey64 +template +struct HashKey64 { + HashKey64() {} + HashKey64(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + uint64 v = (uint64)value; + return (uint32)(v >> 32) ^ (uint32)v; + } + + HashKey64 operator=(const HashKey64& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey64& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey64& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashMap + +// constructor +template +HashMap::HashMap() + : + fElementArray(1000), + fTable(1000, &fElementArray) +{ +} + +// destructor +template +HashMap::~HashMap() +{ +} + +// InitCheck +template +status_t +HashMap::InitCheck() const +{ + return (fTable.InitCheck() && fElementArray.InitCheck() + ? B_OK : B_NO_MEMORY); +} + +// Put +template +status_t +HashMap::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 +Value +HashMap::Remove(const Key& key) +{ + Value value = Value(); + if (Element* element = _FindElement(key)) { + value = element->fValue; + fTable.Remove(element); + } + return value; +} + +// Clear +template +void +HashMap::Clear() +{ + fTable.RemoveAll(); +} + +// Get +template +Value +HashMap::Get(const Key& key) const +{ + if (Element* element = _FindElement(key)) + return element->fValue; + return Value(); +} + +// Get +template +bool +HashMap::Get(const Key& key, Value*& _value) const +{ + if (Element* element = _FindElement(key)) { + _value = &element->fValue; + return true; + } + + return false; +} + +// ContainsKey +template +bool +HashMap::ContainsKey(const Key& key) const +{ + return _FindElement(key); +} + +// Size +template +int32 +HashMap::Size() const +{ + return fTable.CountElements(); +} + +// GetIterator +template +struct HashMap::Iterator +HashMap::GetIterator() const +{ + return Iterator(this); +} + +// _FindElement +template +struct HashMap::Element * +HashMap::_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 diff --git a/src/apps/webpositive/support/HashSet.h b/src/apps/webpositive/support/HashSet.h new file mode 100644 index 0000000000..ee7be71288 --- /dev/null +++ b/src/apps/webpositive/support/HashSet.h @@ -0,0 +1,342 @@ +// HashSet.h +// +// Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de) +// +// 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 + +#include "AutoLocker.h" +#include "OpenHashTable.h" + + +namespace BPrivate { + +// HashSetElement +template +class HashSetElement : public OpenHashElement { +private: + typedef HashSetElement 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(_element); + return (fKey == element.fKey); + } + + inline void Adopt(Element &element) + { + fKey = element.fKey; + } + + Key fKey; +}; + +// HashSet +template +class HashSet { +public: + class Iterator { + private: + typedef HashSetElement 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* 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; + + HashSet* 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 Element; + friend class Iterator; + +private: + Element *_FindElement(const Key& key) const; + +protected: + OpenHashElementArray fElementArray; + OpenHashTable > fTable; +}; + +// SynchronizedHashSet +template +class SynchronizedHashSet : public BLocker { +public: + typedef struct HashSet::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(lock)); + if (!locker.IsLocked()) + return false; + return fSet.Contains(key); + } + + int32 Size() const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + return fSet.Size(); + } + + Iterator GetIterator() + { + return fSet.GetIterator(); + } + + // for debugging only + const HashSet& GetUnsynchronizedSet() const { return fSet; } + HashSet& GetUnsynchronizedSet() { return fSet; } + +protected: + typedef AutoLocker MapLocker; + + HashSet fSet; +}; + +// HashSet + +// constructor +template +HashSet::HashSet() + : fElementArray(1000), + fTable(1000, &fElementArray) +{ +} + +// destructor +template +HashSet::~HashSet() +{ +} + +// InitCheck +template +status_t +HashSet::InitCheck() const +{ + return (fTable.InitCheck() && fElementArray.InitCheck() + ? B_OK : B_NO_MEMORY); +} + +// Add +template +status_t +HashSet::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 +bool +HashSet::Remove(const Key& key) +{ + if (Element* element = _FindElement(key)) { + fTable.Remove(element); + return true; + } + return false; +} + +// Clear +template +void +HashSet::Clear() +{ + fTable.RemoveAll(); +} + +// Contains +template +bool +HashSet::Contains(const Key& key) const +{ + return _FindElement(key); +} + +// Size +template +int32 +HashSet::Size() const +{ + return fTable.CountElements(); +} + +// GetIterator +template +struct HashSet::Iterator +HashSet::GetIterator() +{ + return Iterator(this); +} + +// _FindElement +template +struct HashSet::Element * +HashSet::_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 diff --git a/src/apps/webpositive/support/OpenHashTable.h b/src/apps/webpositive/support/OpenHashTable.h new file mode 100644 index 0000000000..437fbed170 --- /dev/null +++ b/src/apps/webpositive/support/OpenHashTable.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 +#include + +// don't include +#ifndef ASSERT +# define ASSERT(E) (void)0 +#endif +#ifndef TRESPASS +# define TRESPASS() (void)0 +#endif + +namespace BPrivate { + +template +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 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 OpenHashElementArray : public ElementVector { + // 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 +OpenHashTable::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 +OpenHashTable::~OpenHashTable() +{ + RemoveAll(); + free(fHashArray); +} + +template +bool +OpenHashTable::InitCheck() const +{ + return (fHashArray && fElementVector); +} + +template +int32 +OpenHashTable::OptimalSize(int32 minSize) +{ + for (int32 index = 0; ; index++) + if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize) + return (int32)kPrimes[index]; + + return 0; +} + +template +Element * +OpenHashTable::FindFirst(uint32 hash) const +{ + ASSERT(fElementVector); + hash %= fArraySize; + if (fHashArray[hash] < 0) + return 0; + + return &fElementVector->At(fHashArray[hash]); +} + +template +int32 +OpenHashTable::ElementIndex(const Element *element) const +{ + return fElementVector->IndexOf(*element); +} + +template +Element * +OpenHashTable::ElementAt(int32 index) const +{ + return &fElementVector->At(index); +} + +template +int32 +OpenHashTable::ArraySize() const +{ + return fArraySize; +} + +template +int32 +OpenHashTable::VectorSize() const +{ + return fElementVector->Size(); +} + +template +int32 +OpenHashTable::CountElements() const +{ + return fElementCount; +} + + +template +Element * +OpenHashTable::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 +void +OpenHashTable::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 +void +OpenHashTable::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 +void +OpenHashTable::SetElementVector(ElementVec *elementVector) +{ + fElementVector = elementVector; +} + +// _RehashIfNeeded +template +bool +OpenHashTable::_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 +bool +OpenHashTable::_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 +OpenHashElementArray::OpenHashElementArray(int32 initialSize) + : fSize(initialSize), + fNextFree(0), + fNextDeleted(-1) +{ + fData = (Element*)calloc((size_t)initialSize, sizeof(Element)); +} + +template +OpenHashElementArray::~OpenHashElementArray() +{ + free(fData); +} + +template +bool +OpenHashElementArray::InitCheck() const +{ + return fData; +} + +template +Element & +OpenHashElementArray::At(int32 index) +{ + ASSERT(index < fSize); + return fData[index]; +} + +template +const Element & +OpenHashElementArray::At(int32 index) const +{ + ASSERT(index < fSize); + return fData[index]; +} + +template +int32 +OpenHashElementArray::IndexOf(const Element &element) const +{ + int32 result = &element - fData; + if (result < 0 || result > fSize) + return -1; + + return result; +} + +template +int32 +OpenHashElementArray::Size() const +{ + return fSize; +} + + +template +Element * +OpenHashElementArray::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 +Element * +OpenHashElementArray::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 +void +OpenHashElementArray::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__ From 9f30678a6772a544fc0c1d7c14bd329ba5c040cd Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 16:56:54 +0000 Subject: [PATCH 205/293] Implemented a CredentialsStorage class with optional persistency. Two global objects are used for session and persistent storage of credentials with the appropriate locking. Passwords are stored on disk insecurely. If the user uses the checkmark in the authentication window to remember the credentials, the persistent storage will be used, otherwise the session storage. In another words, even if not asked to remember the credentials, the same user/pass never needs to be entered more than once per session, unlike before. WebCore already contains a CredentialStorage class, but we don't use it. It could be used via the CURL networking backend implementation, only the CF backend uses it at all. Since we don't have a "keyring" OS level service, this solution was more convenient for the time being. Note all this has nothing to do with storage of form data entered by the user. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@478 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 32 ++- src/apps/webpositive/BrowserWindow.h | 2 + src/apps/webpositive/CredentialsStorage.cpp | 275 ++++++++++++++++++++ src/apps/webpositive/CredentialsStorage.h | 98 +++++++ 4 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 src/apps/webpositive/CredentialsStorage.cpp create mode 100644 src/apps/webpositive/CredentialsStorage.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d1835a7544..e64906eaf7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BaseURL.h" #include "BrowserApp.h" #include "BrowsingHistory.h" +#include "CredentialsStorage.h" #include "IconButton.h" #include "NavMenu.h" #include "SettingsKeys.h" @@ -1151,6 +1152,27 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, BWebView* view) { + CredentialsStorage* persistentStorage + = CredentialsStorage::PersistentInstance(); + CredentialsStorage* sessionStorage + = CredentialsStorage::SessionInstance(); + + // TODO: Using the message as key here is not so smart. + HashKeyString key(message); + + if (failureCount == 0) { + if (persistentStorage->Contains(key)) { + Credentials credentials = persistentStorage->GetCredentials(key); + inOutUser = credentials.Username(); + inOutPassword = credentials.Password(); + return true; + } else if (sessionStorage->Contains(key)) { + Credentials credentials = sessionStorage->GetCredentials(key); + inOutUser = credentials.Username(); + inOutPassword = credentials.Password(); + return true; + } + } // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { int32 tabIndex = fTabManager->TabForView(view); @@ -1164,9 +1186,17 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. - return panel->getAuthentication(message, inOutUser, inOutPassword, + bool success = panel->getAuthentication(message, inOutUser, inOutPassword, inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, &inOutRememberCredentials); + if (success) { + Credentials credentials(inOutUser, inOutPassword); + if (inOutRememberCredentials) + persistentStorage->PutCredentials(key, credentials); + else + sessionStorage->PutCredentials(key, credentials); + } + return success; } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1dd2951410..0c78abd48a 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -30,6 +30,8 @@ #define BROWSER_WINDOW_H +#include "HashKeys.h" +#include "HashMap.h" #include "WebWindow.h" #include #include diff --git a/src/apps/webpositive/CredentialsStorage.cpp b/src/apps/webpositive/CredentialsStorage.cpp new file mode 100644 index 0000000000..ab5f8eae8d --- /dev/null +++ b/src/apps/webpositive/CredentialsStorage.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +#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; +} + diff --git a/src/apps/webpositive/CredentialsStorage.h b/src/apps/webpositive/CredentialsStorage.h new file mode 100644 index 0000000000..214c36b371 --- /dev/null +++ b/src/apps/webpositive/CredentialsStorage.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * 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 +#include + + +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 CredentialMap; + CredentialMap fCredentialMap; + + static CredentialsStorage sPersistentInstance; + static CredentialsStorage sSessionInstance; + bool fSettingsLoaded; + bool fPersistent; +}; + + +#endif // CREDENTIAL_STORAGE_H + From 27dab3e5fe5e7f8115d8db88f82508168faf27e9 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 18:01:38 +0000 Subject: [PATCH 206/293] Make sure never to draw the favicon too big, in case we only got a big one from the page, and use the proper drawing mode and filtering. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@479 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 40805943fc..d5f4888234 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -532,7 +532,8 @@ public: BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fIcon(NULL) { - SetDrawingMode(B_OP_OVER); + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); } ~PageIconView() @@ -546,21 +547,20 @@ public: return; BRect bounds(Bounds()); - BRect iconBounds(fIcon->Bounds()); - BPoint iconPos( + 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, iconPos); + DrawBitmap(fIcon, fIcon->Bounds(), iconBounds, + B_FILTER_BITMAP_BILINEAR); } virtual BSize MinSize() { - if (fIcon != NULL) { - return BSize(fIcon->Bounds().Width() + 3, - fIcon->Bounds().Height() + 3); - } + if (fIcon != NULL) + return BSize(18, 18); return BSize(0, 0); } From 9adbaa437850184544cd54aaf5c45e91b573a02f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 10:49:16 +0000 Subject: [PATCH 207/293] Removed unneeded headers. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@480 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0c78abd48a..1dd2951410 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -30,8 +30,6 @@ #define BROWSER_WINDOW_H -#include "HashKeys.h" -#include "HashMap.h" #include "WebWindow.h" #include #include From 9a6307059ae614b24fb17805b0ed916aa09d6a9f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 12:02:24 +0000 Subject: [PATCH 208/293] Moved handling/display of "main site error" alert into client. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@481 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 90 ++++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 5 ++ 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e64906eaf7..742b910562 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1009,6 +1009,43 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) } +void +BrowserWindow::MainDocumentError(const BString& failingURL, + const BString& localizedDescription, BWebView* view) +{ + // Make sure we show the page that contains the view. + if (!_ShowPage(view)) + return; + + BWebWindow::MainDocumentError(failingURL, localizedDescription, view); + + // TODO: Remove the failing URL from the BrowsingHistory! +} + + +void +BrowserWindow::TitleChanged(const BString& title, BWebView* view) +{ + for (int32 i = 0; i < fTabManager->CountTabs(); i++) { + if (fTabManager->ViewForTab(i) == view) { + fTabManager->SetTabLabel(i, title); + break; + } + } + if (view != CurrentWebView()) + return; + + _UpdateTitle(title); +} + + +void +BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) +{ + _SetPageIcon(view, icon); +} + + void BrowserWindow::ResizeRequested(float width, float height, BWebView* view) { @@ -1090,29 +1127,6 @@ BrowserWindow::SetResizable(bool flag, BWebView* view) } -void -BrowserWindow::TitleChanged(const BString& title, BWebView* view) -{ - for (int32 i = 0; i < fTabManager->CountTabs(); i++) { - if (fTabManager->ViewForTab(i) == view) { - fTabManager->SetTabLabel(i, title); - break; - } - } - if (view != CurrentWebView()) - return; - - _UpdateTitle(title); -} - - -void -BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) -{ - _SetPageIcon(view, icon); -} - - void BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { @@ -1174,16 +1188,9 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, } } // Switch to the page for which this authentication is required. - if (view != CurrentWebView()) { - int32 tabIndex = fTabManager->TabForView(view); - if (tabIndex < 0) { - // Page seems to be gone already? - return false; - } - fTabManager->SelectTab(tabIndex); - _TabChanged(tabIndex); - UpdateIfNeeded(); - } + if (!_ShowPage(view)) + return false; + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. bool success = panel->getAuthentication(message, inOutUser, inOutPassword, @@ -1669,3 +1676,20 @@ BrowserWindow::_UpdateClipboardItems() CurrentWebView()->WebPage()->SendEditingCapabilities(); } } + + +bool +BrowserWindow::_ShowPage(BWebView* view) +{ + if (view != CurrentWebView()) { + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) { + // Page seems to be gone already? + return false; + } + fTabManager->SelectTab(tabIndex); + _TabChanged(tabIndex); + UpdateIfNeeded(); + } + return true; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1dd2951410..610029ac3d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -113,6 +113,9 @@ private: 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, @@ -159,6 +162,8 @@ private: void _UpdateHistoryMenu(); void _UpdateClipboardItems(); + bool _ShowPage(BWebView* view); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From f157030d2e6f467b0ce61cfca868051fb3868078 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 12:23:56 +0000 Subject: [PATCH 209/293] Implemented most basic fullscreen feature. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@482 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 106 ++++++++++++++++++++----- src/apps/webpositive/BrowserWindow.h | 13 +++ 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 742b910562..44abfb4534 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -76,29 +76,31 @@ enum { - OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + OPEN_LOCATION = 'open', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - CREATE_BOOKMARK = 'crbm', - SHOW_BOOKMARKS = 'shbm', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', - ZOOM_FACTOR_INCREASE = 'zfin', - ZOOM_FACTOR_DECREASE = 'zfdc', - ZOOM_FACTOR_RESET = 'zfrs', - ZOOM_TEXT_ONLY = 'zfto', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', - EDIT_SHOW_FIND_GROUP = 'sfnd', - EDIT_HIDE_FIND_GROUP = 'hfnd', - EDIT_FIND_NEXT = 'fndn', - EDIT_FIND_PREVIOUS = 'fndp', - FIND_TEXT_CHANGED = 'ftxt', + TOGGLE_FULLSCREEN = 'tgfs', - SELECT_TAB = 'sltb', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', + + SELECT_TAB = 'sltb', }; @@ -189,6 +191,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fIsFullscreen(false), fAppSettings(appSettings), fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true) @@ -274,6 +277,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(ZOOM_TEXT_ONLY)); fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); menu->AddItem(fZoomTextOnlyMenuItem); + + menu->AddSeparatorItem(); + fFullscreenItem = new BMenuItem("Fullscreen", + new BMessage(TOGGLE_FULLSCREEN), B_RETURN); + menu->AddItem(fFullscreenItem); + mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -604,6 +613,10 @@ BrowserWindow::MessageReceived(BMessage* message) // already zoomed. break; + case TOGGLE_FULLSCREEN: + _ToggleFullscreen(); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -770,6 +783,29 @@ BrowserWindow::MenusBeginning() } +void +BrowserWindow::Zoom(BPoint origin, float width, float height) +{ + _ToggleFullscreen(); +} + + +void +BrowserWindow::ScreenChanged(BRect screenSize, color_space format) +{ + if (fIsFullscreen) + _ResizeToScreen(); +} + + +void +BrowserWindow::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces) +{ + if (fIsFullscreen) + _ResizeToScreen(); +} + + static bool viewIsChild(const BView* parent, const BView* view) { @@ -1693,3 +1729,35 @@ BrowserWindow::_ShowPage(BWebView* view) } return true; } + + +void +BrowserWindow::_ToggleFullscreen() +{ + if (fIsFullscreen) { + MoveTo(fNonFullscreenWindowFrame.LeftTop()); + ResizeTo(fNonFullscreenWindowFrame.Width(), + fNonFullscreenWindowFrame.Height()); + + SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_DOCUMENT_WINDOW_LOOK); + } else { + fNonFullscreenWindowFrame = Frame(); + _ResizeToScreen(); + + SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_TITLED_WINDOW_LOOK); + } + fIsFullscreen = !fIsFullscreen; + fFullscreenItem->SetMarked(fIsFullscreen); +} + + +void +BrowserWindow::_ResizeToScreen() +{ + BScreen screen(this); + MoveTo(0, 0); + ResizeTo(screen.Frame().Width(), screen.Frame().Height()); +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 610029ac3d..3ae549af66 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -90,6 +90,12 @@ public: 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); void CreateNewTab(const BString& url, bool select, @@ -164,6 +170,9 @@ private: bool _ShowPage(BWebView* view); + void _ToggleFullscreen(); + void _ResizeToScreen(); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; @@ -174,6 +183,7 @@ private: BMenuItem* fFindPreviousMenuItem; BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + BMenuItem* fFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -194,6 +204,9 @@ private: BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + bool fIsFullscreen; + BRect fNonFullscreenWindowFrame; + // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; From 095c4241efc817337f8662d832a6634f74146db3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 16:10:39 +0000 Subject: [PATCH 210/293] Moved BitmapButton into it's own file. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@483 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 87 +------------ src/apps/webpositive/support/BitmapButton.cpp | 116 ++++++++++++++++++ src/apps/webpositive/support/BitmapButton.h | 44 +++++++ 3 files changed, 162 insertions(+), 85 deletions(-) create mode 100644 src/apps/webpositive/support/BitmapButton.cpp create mode 100644 src/apps/webpositive/support/BitmapButton.h diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index d5f4888234..7fec10caaf 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -16,13 +16,13 @@ #include #include #include -#include #include #include #include #include "BaseURL.h" +#include "BitmapButton.h" #include "BrowsingHistory.h" #include "IconButton.h" #include "TextViewCompleter.h" @@ -382,9 +382,6 @@ URLInputGroup::URLTextView::_AlignTextRect() } -// #pragma mark - GoButton - - const uint32 kGoBitmapWidth = 14; const uint32 kGoBitmapHeight = 14; const color_space kGoBitmapFormat = B_RGBA32; @@ -442,87 +439,7 @@ const unsigned char kGoBitmapBits[] = { }; -class BitmapButton : public BButton { - static const float kFrameInset = 2; - -public: - BitmapButton(const char* resourceName, BMessage* message) - : - BButton("", message), - fBitmap(BTranslationUtils::GetBitmap(resourceName)) - { - } - - 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)) - { - memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength()); - } - - ~BitmapButton() - { - delete fBitmap; - } - - virtual BSize 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; - } - - 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); - uint32 flags = be_control_look->Flags(this); - - be_control_look->DrawButtonBackground(this, bounds, updateRect, base, - flags); - - SetDrawingMode(B_OP_ALPHA); - - if (!IsEnabled()) { - SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); - SetHighColor(0, 0, 0, 120); - } - - if (fBitmap == NULL) - return; - 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); - } - -private: - BBitmap* fBitmap; -}; - - -// #pragma mark - IconView +// #pragma mark - PageIconView class URLInputGroup::PageIconView : public BView { diff --git a/src/apps/webpositive/support/BitmapButton.cpp b/src/apps/webpositive/support/BitmapButton.cpp new file mode 100644 index 0000000000..1b4a22cee0 --- /dev/null +++ b/src/apps/webpositive/support/BitmapButton.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2010 Stephan Aßmus . All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "BitmapButton.h" + +#include + +#include +#include +#include + + +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 { + 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(); + } +} + diff --git a/src/apps/webpositive/support/BitmapButton.h b/src/apps/webpositive/support/BitmapButton.h new file mode 100644 index 0000000000..432adcb34e --- /dev/null +++ b/src/apps/webpositive/support/BitmapButton.h @@ -0,0 +1,44 @@ +/* + * Copyright 2010 Stephan Aßmus . All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef BITMAP_BUTTON_H +#define BITMAP_BUTTON_H + +#include + + +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 From c0f79c032172efa3649b0902d1ffbf2411f1e467 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 19:34:13 +0000 Subject: [PATCH 211/293] Added button besides main menu bar which is only visible in fullscreen mode and allows to go back to window'ed mode. The icon is the window icon which Deskbar uses also. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@484 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 19 +++++-- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/support/BitmapButton.cpp | 3 ++ src/apps/webpositive/support/WindowIcon.h | 54 +++++++++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/apps/webpositive/support/WindowIcon.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 44abfb4534..173f947577 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BaseURL.h" +#include "BitmapButton.h" #include "BrowserApp.h" #include "BrowsingHistory.h" #include "CredentialsStorage.h" @@ -47,6 +48,7 @@ #include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" +#include "WindowIcon.h" #include #include #include @@ -376,10 +378,18 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ; + BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, + kWindowIconWidth, kWindowIconHeight, kWindowIconFormat, + new BMessage(TOGGLE_FULLSCREEN)); + toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); + // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(mainMenu) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(mainMenu) + .Add(toggleFullscreenButton, 0.0f) + ) #endif .Add(fTabManager->TabGroup()) .Add(navigationGroup) @@ -400,10 +410,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fNavigationGroup = layoutItemFor(navigationGroup); fFindGroup = layoutItemFor(findGroup); fStatusGroup = layoutItemFor(statusGroup); - - CreateNewTab(url, true, webView); + fToggleFullscreenButton = layoutItemFor(toggleFullscreenButton); fFindGroup->SetVisible(false); + fToggleFullscreenButton->SetVisible(false); + + CreateNewTab(url, true, webView); if (toolbarPolicy == DoNotHaveToolbar) { #if !INTEGRATE_MENU_INTO_TAB_BAR @@ -1750,6 +1762,7 @@ BrowserWindow::_ToggleFullscreen() } fIsFullscreen = !fIsFullscreen; fFullscreenItem->SetMarked(fIsFullscreen); + fToggleFullscreenButton->SetVisible(fIsFullscreen); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 3ae549af66..c7d230c2f0 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -199,6 +199,7 @@ private: BLayoutItem* fNavigationGroup; BLayoutItem* fFindGroup; BLayoutItem* fStatusGroup; + BLayoutItem* fToggleFullscreenButton; BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; diff --git a/src/apps/webpositive/support/BitmapButton.cpp b/src/apps/webpositive/support/BitmapButton.cpp index 1b4a22cee0..009079969c 100644 --- a/src/apps/webpositive/support/BitmapButton.cpp +++ b/src/apps/webpositive/support/BitmapButton.cpp @@ -80,6 +80,9 @@ BitmapButton::Draw(BRect updateRect) 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); } diff --git a/src/apps/webpositive/support/WindowIcon.h b/src/apps/webpositive/support/WindowIcon.h new file mode 100644 index 0000000000..30d1622058 --- /dev/null +++ b/src/apps/webpositive/support/WindowIcon.h @@ -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 +}; + From c2227feb1e1b34c9d9a7025e16fb8ac30302fde6 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 21:54:10 +0000 Subject: [PATCH 212/293] Implemented an "auto-hide the interface" feature for the full-screen mode. The mouse cursor will automatically hide if you don't move it, unless it's over the interface. The interface will disappear after three seconds if the cursor is not above it. It will re-appear when you touch the top of the screen with the mouse. I find this the best solution, since the mouse is also used for navigation in the page, and showing the interface based on some virtual area of the interface would just get in the way. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@485 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 209 +++++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 43 +++-- src/apps/webpositive/SettingsKeys.cpp | 3 + src/apps/webpositive/SettingsKeys.h | 2 + 4 files changed, 192 insertions(+), 65 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 173f947577..68febf2eff 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -78,31 +79,33 @@ enum { - OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + OPEN_LOCATION = 'open', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - CREATE_BOOKMARK = 'crbm', - SHOW_BOOKMARKS = 'shbm', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', - ZOOM_FACTOR_INCREASE = 'zfin', - ZOOM_FACTOR_DECREASE = 'zfdc', - ZOOM_FACTOR_RESET = 'zfrs', - ZOOM_TEXT_ONLY = 'zfto', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', - TOGGLE_FULLSCREEN = 'tgfs', + TOGGLE_FULLSCREEN = 'tgfs', + TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN = 'tgah', + CHECK_AUTO_HIDE_INTERFACE = 'cahi', - EDIT_SHOW_FIND_GROUP = 'sfnd', - EDIT_HIDE_FIND_GROUP = 'hfnd', - EDIT_FIND_NEXT = 'fndn', - EDIT_FIND_PREVIOUS = 'fndp', - FIND_TEXT_CHANGED = 'ftxt', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', - SELECT_TAB = 'sltb', + SELECT_TAB = 'sltb', }; @@ -188,15 +191,18 @@ private: BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, - const BString& url, ToolbarPolicy toolbarPolicy, BWebView* webView) + const BString& url, uint32 interfaceElements, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), fIsFullscreen(false), + fPulseRunner(NULL), + fVisibleInterfaceElements(interfaceElements), fAppSettings(appSettings), fZoomTextOnly(true), - fShowTabsIfSinglePageOpen(true) + fShowTabsIfSinglePageOpen(true), + fAutoHideInterfaceInFullscreenMode(false) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); @@ -284,6 +290,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); + fAutoHideInterfaceInFullscreenItem = new BMenuItem("Auto hide interface " + "in fullscreen mode", + new BMessage(TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN)); + menu->AddItem(fAutoHideInterfaceInFullscreenItem); mainMenu->AddItem(menu); @@ -371,11 +381,15 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) ; - BView* statusGroup = BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fStatusText) - .Add(fLoadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + // Status bar group + BView* statusGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -383,19 +397,20 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); + BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) + .Add(mainMenu) + .Add(toggleFullscreenButton, 0.0f) + ; + // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(BGroupLayoutBuilder(B_HORIZONTAL) - .Add(mainMenu) - .Add(toggleFullscreenButton, 0.0f) - ) + .Add(menuBarGroup) #endif .Add(fTabManager->TabGroup()) .Add(navigationGroup) .Add(fTabManager->ContainerView()) .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(statusGroup) ); @@ -405,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fURLInputGroup->MakeFocus(true); - fMenuGroup = layoutItemFor(mainMenu); + fMenuGroup = layoutItemFor(menuBarGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); fNavigationGroup = layoutItemFor(navigationGroup); fFindGroup = layoutItemFor(findGroup); @@ -416,14 +431,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fToggleFullscreenButton->SetVisible(false); CreateNewTab(url, true, webView); - - if (toolbarPolicy == DoNotHaveToolbar) { -#if !INTEGRATE_MENU_INTO_TAB_BAR - fMenuGroup->SetVisible(false); -#endif - fTabGroup->SetVisible(false); - fNavigationGroup->SetVisible(false); - } + _ShowInterface(true); + _SetAutoHideInterfaceInFullscreen(fAppSettings->GetValue( + kAutoHideInterfaceInFullscreenMode, + fAutoHideInterfaceInFullscreenMode)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); @@ -447,6 +458,7 @@ BrowserWindow::~BrowserWindow() { fAppSettings->RemoveListener(BMessenger(this)); delete fTabManager; + delete fPulseRunner; } @@ -482,6 +494,13 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } } } + if (message->what == B_MOUSE_MOVED || message->what == B_MOUSE_DOWN + || message->what == B_MOUSE_UP) { + message->FindPoint("where", &fLastMousePos); + if (message->FindInt64("when", &fLastMouseMovedTime) != B_OK) + fLastMouseMovedTime = system_time(); + _CheckAutoHideInterface(); + } BWebWindow::DispatchMessage(message, target); } @@ -629,6 +648,15 @@ BrowserWindow::MessageReceived(BMessage* message) _ToggleFullscreen(); break; + case TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN: + _SetAutoHideInterfaceInFullscreen( + !fAutoHideInterfaceInFullscreenMode); + break; + + case CHECK_AUTO_HIDE_INTERFACE: + _CheckAutoHideInterface(); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -758,6 +786,9 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyNewTabPolicy && message->FindUInt32("value", &value) == B_OK) { fNewTabPolicy = value; + } else if (name == kAutoHideInterfaceInFullscreenMode + && message->FindBool("value", &flag) == B_OK) { + _SetAutoHideInterfaceInFullscreen(flag); } break; } @@ -960,7 +991,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, - BString(), DoNotHaveToolbar, view); + BString(), INTERFACE_ELEMENT_STATUS, view); window->Show(); } else CreateNewTab(BString(), activate, view); @@ -1016,13 +1047,11 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) if (view != CurrentWebView()) return; - if (fLoadingProgressBar) { - if (progress < 100 && fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Show(); - else if (progress == 100 && !fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Hide(); - fLoadingProgressBar->SetTo(progress); - } + if (progress < 100 && fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Show(); + else if (progress == 100 && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetTo(progress); } @@ -1035,7 +1064,7 @@ BrowserWindow::LoadFailed(const BString& url, BWebView* view) BString status(url); status << " failed."; view->WebPage()->SetStatusMessage(status); - if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + if (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } @@ -1049,7 +1078,7 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) BString status(url); status << " finished."; view->WebPage()->SetStatusMessage(status); - if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + if (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); NavigationCapabilitiesChanged(fBackButton->IsEnabled(), @@ -1753,6 +1782,8 @@ BrowserWindow::_ToggleFullscreen() SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); SetLook(B_DOCUMENT_WINDOW_LOOK); + + _ShowInterface(true); } else { fNonFullscreenWindowFrame = Frame(); _ResizeToScreen(); @@ -1774,3 +1805,79 @@ BrowserWindow::_ResizeToScreen() ResizeTo(screen.Frame().Width(), screen.Frame().Height()); } + +void +BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) +{ + if (fAutoHideInterfaceInFullscreenMode == doIt) + return; + + fAutoHideInterfaceInFullscreenMode = doIt; + fAutoHideInterfaceInFullscreenItem->SetMarked(doIt); + if (fAppSettings->GetValue(kAutoHideInterfaceInFullscreenMode, doIt) + != doIt) { + fAppSettings->SetValue(kAutoHideInterfaceInFullscreenMode, doIt); + } + + if (fAutoHideInterfaceInFullscreenMode) { + BMessage message(CHECK_AUTO_HIDE_INTERFACE); + fPulseRunner = new BMessageRunner(BMessenger(this), &message, 300000); + } else { + delete fPulseRunner; + fPulseRunner = NULL; + } +} + + +void +BrowserWindow::_CheckAutoHideInterface() +{ + if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode) + return; + + bigtime_t now = system_time(); + float navigationGroupBottom = fNavigationGroup->IsVisible() ? + fNavigationGroup->Frame().bottom : 0; + if (fLastMousePos.y > navigationGroupBottom + && now - fLastMouseMovedTime > 1500000) { + be_app->ObscureCursor(); + } + + if (fLastMousePos.y == 0) + _ShowInterface(true); + else if (fNavigationGroup->IsVisible() + && fLastMousePos.y > fNavigationGroup->Frame().bottom + && now - fLastMouseMovedTime > 3000000) { + // NOTE: Do not re-use navigationGroupBottom in the above + // check, since we only want to hide the interface when it is visible. + _ShowInterface(false); + } +} + + +void +BrowserWindow::_ShowInterface(bool show) +{ + if (show) { +#if !INTEGRATE_MENU_INTO_TAB_BAR + fMenuGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); +#endif + fTabGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fNavigationGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); + fStatusGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_STATUS) != 0); + } else { + fMenuGroup->SetVisible(false); + fTabGroup->SetVisible(false); + fNavigationGroup->SetVisible(false); + fStatusGroup->SetVisible(false); + } + // TODO: Setting the group visible seems to unhide the status bar. + // Fix in Haiku? + if (!fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c7d230c2f0..8956bffa2d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -41,6 +41,7 @@ class BFile; class BLayoutItem; class BMenu; class BMenuItem; +class BMessageRunner; class BPath; class BStatusBar; class BStringView; @@ -51,25 +52,29 @@ class SettingsMessage; class TabManager; class URLInputGroup; -enum ToolbarPolicy { - HaveToolbar, - DoNotHaveToolbar +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 + 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' + 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 @@ -80,7 +85,8 @@ public: BrowserWindow(BRect frame, SettingsMessage* appSettings, const BString& url, - ToolbarPolicy = HaveToolbar, + uint32 interfaceElements + = INTERFACE_ELEMENT_ALL, BWebView* webView = NULL); virtual ~BrowserWindow(); @@ -172,6 +178,9 @@ private: void _ToggleFullscreen(); void _ResizeToScreen(); + void _SetAutoHideInterfaceInFullscreen(bool doIt); + void _CheckAutoHideInterface(); + void _ShowInterface(bool show); private: BMenu* fHistoryMenu; @@ -184,6 +193,7 @@ private: BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; BMenuItem* fFullscreenItem; + BMenuItem* fAutoHideInterfaceInFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -207,11 +217,16 @@ private: bool fIsFullscreen; BRect fNonFullscreenWindowFrame; + BMessageRunner* fPulseRunner; + uint32 fVisibleInterfaceElements; + bigtime_t fLastMouseMovedTime; + BPoint fLastMousePos; // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; + bool fAutoHideInterfaceInFullscreenMode; uint32 fNewWindowPolicy; uint32 fNewTabPolicy; BString fStartPageURL; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index d525ba6aeb..f9e3de942f 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -45,3 +45,6 @@ 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"; + +const char* kAutoHideInterfaceInFullscreenMode + = "auto hide interface in full screen mode"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 6be0e5e15c..87abb6be7d 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -46,4 +46,6 @@ extern const char* kSettingsKeyUseProxy; extern const char* kSettingsKeyProxyAddress; extern const char* kSettingsKeyProxyPort; +extern const char* kAutoHideInterfaceInFullscreenMode; + #endif // SETTINGS_KEYS_H From ea40bbf2d1618534fa28d8a977a21a60cb073ca0 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 22:36:04 +0000 Subject: [PATCH 213/293] * Moved "Auto-hide" menu item into Settings window, as a check box along the "show tabs if single page only" option. * Fixed problems with showing tabs when opening new tabs while the interface was hidden. Introduced a new flag which tracks the hidden state to make this easier. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@486 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 35 ++++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 2 +- src/apps/webpositive/SettingsKeys.cpp | 5 ++-- src/apps/webpositive/SettingsKeys.h | 3 +-- src/apps/webpositive/SettingsWindow.cpp | 18 +++++++++++++ src/apps/webpositive/SettingsWindow.h | 1 + 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 68febf2eff..75f1757ace 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -197,6 +197,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), fIsFullscreen(false), + fInterfaceVisible(false), fPulseRunner(NULL), fVisibleInterfaceElements(interfaceElements), fAppSettings(appSettings), @@ -290,11 +291,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); - fAutoHideInterfaceInFullscreenItem = new BMenuItem("Auto hide interface " - "in fullscreen mode", - new BMessage(TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN)); - menu->AddItem(fAutoHideInterfaceInFullscreenItem); - mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -433,7 +429,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, CreateNewTab(url, true, webView); _ShowInterface(true); _SetAutoHideInterfaceInFullscreen(fAppSettings->GetValue( - kAutoHideInterfaceInFullscreenMode, + kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); @@ -786,7 +782,7 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyNewTabPolicy && message->FindUInt32("value", &value) == B_OK) { fNewTabPolicy = value; - } else if (name == kAutoHideInterfaceInFullscreenMode + } else if (name == kSettingsKeyAutoHideInterfaceInFullscreenMode && message->FindBool("value", &flag) == B_OK) { _SetAutoHideInterfaceInFullscreen(flag); } @@ -956,6 +952,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fURLInputGroup->MakeFocus(true); } + _ShowInterface(true); _UpdateTabGroupVisibility(); } @@ -1302,8 +1299,10 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - fTabGroup->SetVisible(fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1); + if (fInterfaceVisible) { + fTabGroup->SetVisible(fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1); + } fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } @@ -1813,10 +1812,10 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) return; fAutoHideInterfaceInFullscreenMode = doIt; - fAutoHideInterfaceInFullscreenItem->SetMarked(doIt); - if (fAppSettings->GetValue(kAutoHideInterfaceInFullscreenMode, doIt) - != doIt) { - fAppSettings->SetValue(kAutoHideInterfaceInFullscreenMode, doIt); + if (fAppSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + doIt) != doIt) { + fAppSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + doIt); } if (fAutoHideInterfaceInFullscreenMode) { @@ -1858,13 +1857,19 @@ BrowserWindow::_CheckAutoHideInterface() void BrowserWindow::_ShowInterface(bool show) { + if (fInterfaceVisible == show) + return; + + fInterfaceVisible = show; + if (show) { #if !INTEGRATE_MENU_INTO_TAB_BAR fMenuGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); #endif - fTabGroup->SetVisible( - (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fTabGroup->SetVisible((fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1) + && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); fNavigationGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); fStatusGroup->SetVisible( diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 8956bffa2d..1750584fb3 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -193,7 +193,6 @@ private: BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; BMenuItem* fFullscreenItem; - BMenuItem* fAutoHideInterfaceInFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -216,6 +215,7 @@ private: TabManager* fTabManager; bool fIsFullscreen; + bool fInterfaceVisible; BRect fNonFullscreenWindowFrame; BMessageRunner* fPulseRunner; uint32 fVisibleInterfaceElements; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index f9e3de942f..b65abd8da0 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -30,6 +30,8 @@ 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* kSettingsKeyNewWindowPolicy = "new window policy"; const char* kSettingsKeyNewTabPolicy = "new tab policy"; @@ -45,6 +47,3 @@ 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"; - -const char* kAutoHideInterfaceInFullscreenMode - = "auto hide interface in full screen mode"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 87abb6be7d..08fc6077be 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -32,6 +32,7 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; +extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode; extern const char* kSettingsKeyNewWindowPolicy; extern const char* kSettingsKeyNewTabPolicy; @@ -46,6 +47,4 @@ extern const char* kSettingsKeyUseProxy; extern const char* kSettingsKeyProxyAddress; extern const char* kSettingsKeyProxyPort; -extern const char* kAutoHideInterfaceInFullscreenMode; - #endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index b9fa66136a..5026f867dc 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -70,6 +70,7 @@ enum { MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', + MSG_AUTO_HIDE_BEHAVIOR_CHANGED = 'ahbc', MSG_STANDARD_FONT_CHANGED = 'stfc', MSG_SERIF_FONT_CHANGED = 'sefc', @@ -195,6 +196,7 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_NEW_TABS_BEHAVIOR_CHANGED: case MSG_HISTORY_MENU_DAYS_CHANGED: case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_BEHAVIOR_CHANGED: case MSG_STANDARD_FONT_CHANGED: case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: @@ -311,6 +313,11 @@ SettingsWindow::_CreateGeneralPage(float spacing) new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); + fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface", + TR("Auto-hide interface in fullscreen mode."), + new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); + fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF); + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) @@ -332,6 +339,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .Add(fShowTabsIfOnlyOnePage) + .Add(fAutoHideInterfaceInFullscreenMode) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -499,6 +507,11 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON) != fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + canApply = canApply || ( + (fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + false)); + canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -560,6 +573,8 @@ SettingsWindow::_ApplySettings() fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON); // New page policies fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); @@ -622,6 +637,9 @@ SettingsWindow::_RevertSettings() fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + fAutoHideInterfaceInFullscreenMode->SetValue( + fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + false)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index c595632f8e..cfd8f54ce9 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -96,6 +96,7 @@ private: BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; + BCheckBox* fAutoHideInterfaceInFullscreenMode; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From e7c6e9f7476fbcf4524baa322f4b831ff81e94c6 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 5 May 2010 10:24:38 +0000 Subject: [PATCH 214/293] Reset the page icon in the URL input for new tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@487 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 75f1757ace..ee72d6b890 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -935,8 +935,8 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) if (CurrentWebView() != NULL) url = CurrentWebView()->MainFrameURL(); break; - default: case OpenBlankPage: + default: break; } } @@ -948,6 +948,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); webView->WebPage()->ResendNotifications(); + fURLInputGroup->SetPageIcon(NULL); fURLInputGroup->SetText(url.String()); fURLInputGroup->MakeFocus(true); } From e07fc6b71df68266b262583b4d9ca43138ea6c9f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 5 May 2010 11:04:24 +0000 Subject: [PATCH 215/293] * Changed the implementation of context menus in DownloadProgressViews. The views were intercepting mouse messages even if the window was not showing. Now secondary clicks are intercepted in DownloadWindow and the target view is found, which makes this much cheaper. * Offset context menus by 2 pixels, so the mouse does not start directly over an item. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@488 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++--- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/DownloadProgressView.cpp | 52 +++++++------------ src/apps/webpositive/DownloadProgressView.h | 4 +- src/apps/webpositive/DownloadWindow.cpp | 30 +++++++++++ src/apps/webpositive/DownloadWindow.h | 2 + 6 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ee72d6b890..92873f1d97 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1300,16 +1300,22 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - if (fInterfaceVisible) { - fTabGroup->SetVisible(fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1); - } + if (fInterfaceVisible) + fTabGroup->SetVisible(_TabGroupShouldBeVisible()); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } } +bool +BrowserWindow::_TabGroupShouldBeVisible() const +{ + return (fShowTabsIfSinglePageOpen || fTabManager->CountTabs() > 1) + && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0; +} + + void BrowserWindow::_ShutdownTab(int32 index) { @@ -1868,9 +1874,7 @@ BrowserWindow::_ShowInterface(bool show) fMenuGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); #endif - fTabGroup->SetVisible((fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1) - && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fTabGroup->SetVisible(_TabGroupShouldBeVisible()); fNavigationGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); fStatusGroup->SetVisible( diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1750584fb3..5d272b2eb8 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -152,6 +152,7 @@ private: private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); + bool _TabGroupShouldBeVisible() const; void _ShutdownTab(int32 index); void _TabChanged(int32 index); diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index e7914e8736..f0c4e5bb3b 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -208,10 +208,6 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) bool DownloadProgressView::Init(BMessage* archive) { - // We need to receive mouse events even for the areas of children views, - // so we can pop up a context menu. - SetEventMask(B_POINTER_EVENTS); - fCurrentSize = 0; fExpectedSize = 0; fLastUpdateTime = 0; @@ -339,35 +335,6 @@ DownloadProgressView::AllAttached() } -void -DownloadProgressView::MouseDown(BPoint where) -{ - if (!Bounds().Contains(where)) - return; - - int32 buttons; - if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) - return; - - if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) - return; - - where = ConvertToScreen(where) + 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(where, true, true, true); -} - - void DownloadProgressView::Draw(BRect updateRect) { @@ -588,6 +555,25 @@ DownloadProgressView::MessageReceived(BMessage* 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 { diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index 256245442d..32a021b169 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -57,12 +57,12 @@ public: virtual void DetachedFromWindow(); virtual void AllAttached(); - virtual void MouseDown(BPoint where); - virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); + void ShowContextMenu(BPoint screenWhere); + BWebDownload* Download() const; const BString& URL() const; bool IsMissing() const; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 7fa39a6b0a..00d57dc50f 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -198,6 +198,36 @@ DownloadWindow::~DownloadWindow() } +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( + 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) { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 92d299c89b..e4e62bfecc 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -45,6 +45,8 @@ public: SettingsMessage* settings); virtual ~DownloadWindow(); + virtual void DispatchMessage(BMessage* message, + BHandler* target); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); From 17813bda8c2c42afa1505e51340833183cf0c407 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 11 May 2010 12:01:39 +0000 Subject: [PATCH 216/293] Do not advertize support for types we don't actually support. These are handled by the urlwrapper anyway. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@489 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 1079ab970a..5b89991cc9 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -15,8 +15,6 @@ resource app_flags B_SINGLE_LAUNCH; resource file_types message { "types" = "text/html", "types" = "image/svg+xml", - "types" = "application/x-vnd.Be-bookmark", - "types" = "application/x-vnd.Be-doc_bookmark", "types" = "application/x-vnd.Be.URL.file", "types" = "application/x-vnd.Be.URL.ftp", "types" = "application/x-vnd.Be.URL.http", From 59b99c122942d421d4f37bedcda7112ca96222e0 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 11 May 2010 12:15:22 +0000 Subject: [PATCH 217/293] Upated to use new B_TRANSLATE macros. Rene also send me a patch for this (thanks!), but I've redone it to keep the 80 char/line limit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@493 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 92 +++++++++++-------- .../webpositive/support/FontSelectionView.cpp | 18 ++-- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 5026f867dc..64a75a7117 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -55,8 +55,8 @@ #include "WebSettings.h" -#undef TR_CONTEXT -#define TR_CONTEXT "Settings Window" +#undef B_TRANSLATE_CONTEXT +#define B_TRANSLATE_CONTEXT "Settings Window" enum { MSG_APPLY = 'aply', @@ -90,15 +90,18 @@ static const int32 kDefaultFontSize = 14; SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : - BWindow(frame, TR("Settings"), B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + 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(TR("Apply"), new BMessage(MSG_APPLY)); - fCancelButton = new BButton(TR("Cancel"), new BMessage(MSG_CANCEL)); - fRevertButton = new BButton(TR("Revert"), new BMessage(MSG_REVERT)); + 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(); @@ -241,40 +244,49 @@ BView* SettingsWindow::_CreateGeneralPage(float spacing) { fStartPageControl = new BTextControl("start page", - TR("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); + 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", - TR("Search page:"), "", new BMessage(MSG_SEARCH_PAGE_CHANGED)); + 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", - TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); + 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(TR("Open start page"), + fNewWindowBehaviorOpenHomeItem = new BMenuItem( + B_TRANSLATE("Open start page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewWindowBehaviorOpenSearchItem = new BMenuItem( + B_TRANSLATE("Open search page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + fNewWindowBehaviorOpenBlankItem = new BMenuItem( + B_TRANSLATE("Open blank page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + fNewTabBehaviorCloneCurrentItem = new BMenuItem( + B_TRANSLATE("Clone current page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), + fNewTabBehaviorOpenHomeItem = new BMenuItem( + B_TRANSLATE("Open start page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewTabBehaviorOpenSearchItem = new BMenuItem( + B_TRANSLATE("Open search page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + fNewTabBehaviorOpenBlankItem = new BMenuItem( + B_TRANSLATE("Open blank page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenHomeItem->SetMarked(true); @@ -285,7 +297,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem); newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem); fNewWindowBehaviorMenu = new BMenuField("new window behavior", - TR("New windows:"), newWindowBehaviorMenu); + B_TRANSLATE("New windows:"), newWindowBehaviorMenu); BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); @@ -293,10 +305,10 @@ SettingsWindow::_CreateGeneralPage(float spacing) newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); fNewTabBehaviorMenu = new BMenuField("new tab behavior", - TR("New tabs:"), newTabBehaviorMenu); + B_TRANSLATE("New tabs:"), newTabBehaviorMenu); fDaysInHistoryMenuControl = new BTextControl("days in history", - TR("Number of days to keep links in History menu:"), "", + 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)); @@ -309,12 +321,12 @@ SettingsWindow::_CreateGeneralPage(float spacing) fDaysInHistoryMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", - TR("Show tabs if only one page is open."), + 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", - TR("Auto-hide interface in fullscreen mode."), + B_TRANSLATE("Auto-hide interface in fullscreen mode."), new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF); @@ -345,7 +357,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("General")); + view->SetName(B_TRANSLATE("General")); return view; } @@ -353,22 +365,25 @@ SettingsWindow::_CreateGeneralPage(float spacing) BView* SettingsWindow::_CreateFontsPage(float spacing) { - fStandardFontView = new FontSelectionView("standard", TR("Standard font:"), - true, be_plain_font); + fStandardFontView = new FontSelectionView("standard", + B_TRANSLATE("Standard font:"), true, be_plain_font); BFont defaultSerifFont = _FindDefaultSerifFont(); - fSerifFontView = new FontSelectionView("serif", TR("Serif font:"), true, - &defaultSerifFont); + fSerifFontView = new FontSelectionView("serif", + B_TRANSLATE("Serif font:"), true, &defaultSerifFont); fSansSerifFontView = new FontSelectionView("sans serif", - TR("Sans serif font:"), true, be_plain_font); - fFixedFontView = new FontSelectionView("fixed", TR("Fixed font:"), true, - be_fixed_font); + 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", - TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"), + NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), + MSG_STANDARD_FONT_SIZE_SELECTED); fFixedSizesMenu = new BMenuField("fixed font size", - TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"), + NULL); _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -399,7 +414,7 @@ SettingsWindow::_CreateFontsPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("Fonts")); + view->SetName(B_TRANSLATE("Fonts")); return view; } @@ -408,12 +423,12 @@ BView* SettingsWindow::_CreateProxyPage(float spacing) { fUseProxyCheckBox = new BCheckBox("use proxy", - TR("Use proxy server to connect to the internet."), + 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", - TR("Proxy server address:"), "", + B_TRANSLATE("Proxy server address:"), "", new BMessage(MSG_PROXY_ADDRESS_CHANGED)); fProxyAddressControl->SetModificationMessage( new BMessage(MSG_PROXY_ADDRESS_CHANGED)); @@ -421,7 +436,8 @@ SettingsWindow::_CreateProxyPage(float spacing) fSettings->GetValue(kSettingsKeyProxyAddress, "")); fProxyPortControl = new BTextControl("proxy port", - TR("Proxy server port:"), "", new BMessage(MSG_PROXY_PORT_CHANGED)); + B_TRANSLATE("Proxy server port:"), "", + new BMessage(MSG_PROXY_PORT_CHANGED)); fProxyPortControl->SetModificationMessage( new BMessage(MSG_PROXY_PORT_CHANGED)); fProxyPortControl->SetText( @@ -440,7 +456,7 @@ SettingsWindow::_CreateProxyPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("Proxy server")); + view->SetName(B_TRANSLATE("Proxy server")); return view; } diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index c463a8c9ef..81ce76bcb0 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -26,8 +26,8 @@ #include -#undef TR_CONTEXT -#define TR_CONTEXT "Font Selection view" +#undef B_TRANSLATE_CONTEXT +#define B_TRANSLATE_CONTEXT "Font Selection view" static const float kMinSize = 8.0; @@ -65,22 +65,26 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, // styles menu, if desired if (separateStyles) { fStylesMenu = new BPopUpMenu("styles menu"); - fStylesMenuField = new BMenuField("styles", TR("Style:"), fStylesMenu, - NULL); + fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"), + fStylesMenu, NULL); } else { fStylesMenu = NULL; fStylesMenuField = NULL; } // size menu - fSizesMenuField = new BMenuField("size", TR("Size:"), fSizesMenu, NULL); + fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu, + NULL); fSizesMenuField->SetAlignment(B_ALIGN_RIGHT); // preview fPreviewText = new BStringView("preview text", - TR_CMT("The quick brown fox jumps over the lazy dog.","Don't translate this literally ! Use a phrase showing all chars from A to Z.")); + 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->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); From 208ecbcad581862d4fa35d792180cad8cc46195e Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 19:37:33 +0000 Subject: [PATCH 218/293] * Moved auto-hiding the mouse pointer into BWebView::Pulse(). * Unhide the interface when the user invokes CMD-L (Open location). * Make sure the progress bar is really hidden, sometimes it would be visible again after unhiding the rest of the interface. * Added a setting for the auto-hiding the mouse pointer feature. It defaults to true, since I think it's useful for an app where the pointer would usually be in the way. * Hide the mouse pointer in any case as soon as the user begins typing, also hide potentially showing tool tips in that case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@496 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 28 +++++++----- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/SettingsKeys.cpp | 1 + src/apps/webpositive/SettingsKeys.h | 1 + src/apps/webpositive/SettingsWindow.cpp | 60 ++++++++++++++++--------- src/apps/webpositive/SettingsWindow.h | 1 + 6 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 92873f1d97..bc588402db 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -203,7 +203,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fAppSettings(appSettings), fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true), - fAutoHideInterfaceInFullscreenMode(false) + fAutoHideInterfaceInFullscreenMode(false), + fAutoHidePointer(true) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); @@ -211,6 +212,9 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fShowTabsIfSinglePageOpen = fAppSettings->GetValue( kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + fAutoHidePointer = fAppSettings->GetValue(kSettingsKeyAutoHidePointer, + fAutoHidePointer); + fNewWindowPolicy = fAppSettings->GetValue(kSettingsKeyNewWindowPolicy, (uint32)OpenStartPage); fNewTabPolicy = fAppSettings->GetValue(kSettingsKeyNewTabPolicy, @@ -506,6 +510,7 @@ BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { case OPEN_LOCATION: + _ShowInterface(true); if (fURLInputGroup->TextView()->IsFocus()) fURLInputGroup->TextView()->SelectAll(); else @@ -770,6 +775,11 @@ BrowserWindow::MessageReceived(BMessage* message) fShowTabsIfSinglePageOpen = flag; _UpdateTabGroupVisibility(); } + } else if (name == kSettingsKeyAutoHidePointer + && message->FindBool("value", &flag) == B_OK) { + fAutoHidePointer = flag; + if (CurrentWebView()) + CurrentWebView()->SetAutoHidePointer(fAutoHidePointer); } else if (name == kSettingsKeyStartPageURL && message->FindString("value", &string) == B_OK) { fStartPageURL = string; @@ -882,6 +892,8 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) BWebWindow::SetCurrentWebView(webView); if (webView != NULL) { + webView->SetAutoHidePointer(fAutoHidePointer); + _UpdateTitle(webView->MainFrameTitle()); // Restore the previous focus or focus the web view. @@ -1838,22 +1850,16 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) void BrowserWindow::_CheckAutoHideInterface() { - if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode) + if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode + || (CurrentWebView() != NULL && !CurrentWebView()->IsFocus())) { return; - - bigtime_t now = system_time(); - float navigationGroupBottom = fNavigationGroup->IsVisible() ? - fNavigationGroup->Frame().bottom : 0; - if (fLastMousePos.y > navigationGroupBottom - && now - fLastMouseMovedTime > 1500000) { - be_app->ObscureCursor(); } if (fLastMousePos.y == 0) _ShowInterface(true); else if (fNavigationGroup->IsVisible() && fLastMousePos.y > fNavigationGroup->Frame().bottom - && now - fLastMouseMovedTime > 3000000) { + && system_time() - fLastMouseMovedTime > 3000000) { // NOTE: Do not re-use navigationGroupBottom in the above // check, since we only want to hide the interface when it is visible. _ShowInterface(false); @@ -1887,7 +1893,7 @@ BrowserWindow::_ShowInterface(bool show) } // TODO: Setting the group visible seems to unhide the status bar. // Fix in Haiku? - if (!fLoadingProgressBar->IsHidden()) + while (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 5d272b2eb8..4fd972fcce 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -228,6 +228,7 @@ private: bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; bool fAutoHideInterfaceInFullscreenMode; + bool fAutoHidePointer; uint32 fNewWindowPolicy; uint32 fNewTabPolicy; BString fStartPageURL; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index b65abd8da0..5bd2f32cb9 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -32,6 +32,7 @@ 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* kSettingsKeyNewWindowPolicy = "new window policy"; const char* kSettingsKeyNewTabPolicy = "new tab policy"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 08fc6077be..8f2b96de35 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -33,6 +33,7 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode; +extern const char* kSettingsKeyAutoHidePointer; extern const char* kSettingsKeyNewWindowPolicy; extern const char* kSettingsKeyNewTabPolicy; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 64a75a7117..8cfece44f9 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -59,30 +59,31 @@ #define B_TRANSLATE_CONTEXT "Settings Window" enum { - MSG_APPLY = 'aply', - MSG_CANCEL = 'cncl', - MSG_REVERT = 'rvrt', + 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_BEHAVIOR_CHANGED = 'ahbc', + 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_STANDARD_FONT_CHANGED = 'stfc', - MSG_SERIF_FONT_CHANGED = 'sefc', - MSG_SANS_SERIF_FONT_CHANGED = 'ssfc', - MSG_FIXED_FONT_CHANGED = 'ffch', + 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_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', + MSG_USE_PROXY_CHANGED = 'upsc', + MSG_PROXY_ADDRESS_CHANGED = 'psac', + MSG_PROXY_PORT_CHANGED = 'pspc', }; static const int32 kDefaultFontSize = 14; @@ -199,7 +200,8 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_NEW_TABS_BEHAVIOR_CHANGED: case MSG_HISTORY_MENU_DAYS_CHANGED: case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: - case MSG_AUTO_HIDE_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED: case MSG_STANDARD_FONT_CHANGED: case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: @@ -327,9 +329,14 @@ SettingsWindow::_CreateGeneralPage(float spacing) fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface", B_TRANSLATE("Auto-hide interface in fullscreen mode."), - new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); + 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_ON); + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) @@ -352,6 +359,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .Add(fShowTabsIfOnlyOnePage) .Add(fAutoHideInterfaceInFullscreenMode) + .Add(fAutoHidePointer) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -528,6 +536,10 @@ SettingsWindow::_CanApplySettings() const != fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); + canApply = canApply || ( + (fAutoHidePointer->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -591,6 +603,8 @@ SettingsWindow::_ApplySettings() fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyAutoHidePointer, + fAutoHidePointer->Value() == B_CONTROL_ON); // New page policies fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); @@ -656,6 +670,8 @@ SettingsWindow::_RevertSettings() fAutoHideInterfaceInFullscreenMode->SetValue( fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); + fAutoHidePointer->SetValue( + fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index cfd8f54ce9..9648860bff 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -97,6 +97,7 @@ private: BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; + BCheckBox* fAutoHidePointer; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 0e4207931358115f232a09f5cf5b3e49efaee387 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 20:41:50 +0000 Subject: [PATCH 219/293] Remember the current URL input contents and selection when switching away from a tab, and restore them when switching back. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@498 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 66 ++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index bc588402db..98068501b5 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -148,7 +148,9 @@ public: PageUserData(BView* focusedView) : fFocusedView(focusedView), - fPageIcon(NULL) + fPageIcon(NULL), + fURLInputSelectionStart(-1), + fURLInputSelectionEnd(-1) { } @@ -181,9 +183,38 @@ public: return fPageIcon; } + void SetURLInputContents(const char* text) + { + fURLInputContents = text; + } + + const char* URLInputContents() const + { + return fURLInputContents.String(); + } + + void SetURLInputSelection(int32 selectionStart, int32 selectionEnd) + { + fURLInputSelectionStart = selectionStart; + fURLInputSelectionEnd = selectionEnd; + } + + int32 URLInputSelectionStart() const + { + return fURLInputSelectionStart; + } + + int32 URLInputSelectionEnd() const + { + return fURLInputSelectionEnd; + } + private: BView* fFocusedView; BBitmap* fPageIcon; + BString fURLInputContents; + int32 fURLInputSelectionStart; + int32 fURLInputSelectionEnd; }; @@ -883,10 +914,17 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) // later. PageUserData* userData = static_cast( CurrentWebView()->GetUserData()); - if (userData) - userData->SetFocusedView(CurrentFocus()); - else - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (userData == NULL) { + userData = new PageUserData(CurrentFocus()); + CurrentWebView()->SetUserData(userData); + } + userData->SetFocusedView(CurrentFocus()); + userData->SetURLInputContents(fURLInputGroup->Text()); + int32 selectionStart; + int32 selectionEnd; + fURLInputGroup->TextView()->GetSelection(&selectionStart, + &selectionEnd); + userData->SetURLInputSelection(selectionStart, selectionEnd); } BWebWindow::SetCurrentWebView(webView); @@ -900,10 +938,8 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) PageUserData* userData = static_cast( webView->GetUserData()); BView* focusedView = NULL; - if (userData != NULL) { + if (userData != NULL) focusedView = userData->FocusedView(); - fURLInputGroup->SetPageIcon(userData->PageIcon()); - } if (focusedView != NULL && viewIsChild(GetLayout()->View(), focusedView)) { @@ -911,7 +947,19 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) } else webView->MakeFocus(true); - fURLInputGroup->SetText(webView->MainFrameURL()); + if (userData != NULL) { + fURLInputGroup->SetPageIcon(userData->PageIcon()); + fURLInputGroup->SetText(userData->URLInputContents()); + if (userData->URLInputSelectionStart() >= 0) { + fURLInputGroup->TextView()->Select( + userData->URLInputSelectionStart(), + userData->URLInputSelectionEnd()); + } + } else { + fURLInputGroup->SetPageIcon(NULL); + fURLInputGroup->SetText(webView->MainFrameURL()); + } + // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); From eb44597cd09e566abafdf55ed3e03efd03d6a963 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 20:56:35 +0000 Subject: [PATCH 220/293] Revert r250, since CMD-0 for changing to the tenth tab conflicts with the shortcut for resetting the page zoom, but that is also an established shortcut from Firefox. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@499 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 98068501b5..49a0dc3a11 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -470,12 +470,9 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); // Add shortcuts to select a particular tab - for (int32 i = 0; i <= 9; i++) { + for (int32 i = 1; i <= 9; i++) { BMessage *selectTab = new BMessage(SELECT_TAB); - if (i == 0) - selectTab->AddInt32("tab index", 9); - else - selectTab->AddInt32("tab index", i - 1); + selectTab->AddInt32("tab index", i - 1); char numStr[2]; snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); From 90a69c8e1d42bbe82b16a9caadad3fefca92f655 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 16:59:34 +0000 Subject: [PATCH 221/293] The mechanism with which the TextViewCompleter detected changes (attaching a BMessageFilter to the BTextView to pre-process key down events) missed changes to the BTextView via other means, for example by pasting, or simply when SetText() is invoked on the BTextView. -> Introduced an alternative method of making the TextViewCompleter aware of changes, by invoking new method TextModified(). To bypass the old method, one has to call SetModificationsReported(true). URLInput::URLTextView now uses the new method in InsertText() and DeleteText(), which catches any and all changes to the text. Since the BAutoCompleter framework also controls the editor view contents, it needs to protect against re-entering some methods when the editor view reports the changes (fIgnoreEditViewStateChanges). Since we want the BAutoCompleter to always be aware of the current editor view contents, but not necessarily also running the choice mechanism (i.e. when you enter "www.google.com", you don't want the auto-completion kick back in when it is programmatically changed to "http://www.google.com" later on), the EditViewStateChange() method gets a boolean now "updateChoices". All programmatic changes to the URL will then not trigger displaying the choice pop-up, but the BAutoCompleter is always aware of the current editor view contents. All this fixes numerous issues and inconsistencies with entering text in the URL text view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@500 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 32 +++++++++++++++-- .../autocompletion/AutoCompleter.cpp | 4 +-- .../autocompletion/AutoCompleter.h | 5 +-- .../AutoCompleterDefaultImpl.cpp | 29 ++++++++++++---- .../autocompletion/AutoCompleterDefaultImpl.h | 3 +- .../autocompletion/TextViewCompleter.cpp | 34 +++++++++++++++---- .../autocompletion/TextViewCompleter.h | 5 +++ 7 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 7fec10caaf..e5d5c9ecb3 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -148,10 +148,14 @@ public: 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(); @@ -159,6 +163,7 @@ private: URLInputGroup* fURLInputGroup; TextViewCompleter* fURLAutoCompleter; BString fPreviousText; + bool fUpdateAutoCompleterChoices; }; @@ -168,10 +173,12 @@ URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) fURLInputGroup(parent), fURLAutoCompleter(new TextViewCompleter(this, new BrowsingHistoryChoiceModel())), - fPreviousText("") + fPreviousText(""), + fUpdateAutoCompleterChoices(true) { MakeResizable(true); SetStylable(true); + fURLAutoCompleter->SetModificationsReported(true); } @@ -318,6 +325,13 @@ URLInputGroup::URLTextView::MaxSize() } +void +URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update) +{ + fUpdateAutoCompleterChoices = update; +} + + void URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns) @@ -360,6 +374,17 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, 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); } @@ -599,8 +624,11 @@ URLInputGroup::TextView() const void URLInputGroup::SetText(const char* text) { - if (!text || !Text() || strcmp(Text(), text) != 0) + if (!text || !Text() || strcmp(Text(), text) != 0) { + fTextView->SetUpdateAutoCompleterChoices(false); fTextView->SetText(text); + fTextView->SetUpdateAutoCompleterChoices(true); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index 98b659da40..2e5d45e164 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -175,10 +175,10 @@ BAutoCompleter::CancelChoice() void -BAutoCompleter::EditViewStateChanged() +BAutoCompleter::EditViewStateChanged(bool updateChoices) { if (fCompletionStyle) - fCompletionStyle->EditViewStateChanged(); + fCompletionStyle->EditViewStateChanged(updateChoices); } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 8b5cb7be37..16a94559b4 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -101,7 +101,7 @@ public: virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; - virtual void EditViewStateChanged() = 0; + virtual void EditViewStateChanged(bool updateChoices) = 0; void SetEditView(EditView* view); void SetPatternSelector(PatternSelector* selector); @@ -130,7 +130,8 @@ protected: PatternSelector* patternSelector); virtual ~BAutoCompleter(); - void EditViewStateChanged(); + void EditViewStateChanged( + bool updateChoices = true); bool Select(int32 index); bool SelectNext(bool wrap = false); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 95ce32c7a0..5760852400 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -15,6 +15,7 @@ // #pragma mark - BDefaultPatternSelector + void BDefaultPatternSelector::SelectPatternBounds(const BString& text, int32 caretPos, int32* start, int32* length) @@ -38,7 +39,8 @@ BDefaultCompletionStyle::BDefaultCompletionStyle( CompletionStyle(editView, choiceModel, choiceView, patternSelector), fSelectedIndex(-1), fPatternStartPos(0), - fPatternLength(0) + fPatternLength(0), + fIgnoreEditViewStateChanges(false) { } @@ -114,15 +116,19 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text(); completedText.Insert(choiceStr, fPatternStartPos); + fIgnoreEditViewStateChanges = true; + fFullEnteredText = completedText; fPatternLength = choiceStr.Length(); fEditView->SetEditViewState(completedText, - fPatternStartPos+choiceStr.Length()); + fPatternStartPos + choiceStr.Length()); if (hideChoices) { fChoiceView->HideChoices(); Select(-1); } + + fIgnoreEditViewStateChanges = false; } @@ -132,25 +138,36 @@ BDefaultCompletionStyle::CancelChoice() if (!fChoiceView || !fEditView) return; if (fChoiceView->ChoicesAreShown()) { - fEditView->SetEditViewState(fFullEnteredText, - fPatternStartPos+fPatternLength); + fIgnoreEditViewStateChanges = true; + + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos + fPatternLength); fChoiceView->HideChoices(); Select(-1); + + fIgnoreEditViewStateChanges = false; } } void -BDefaultCompletionStyle::EditViewStateChanged() +BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices) { - if (!fChoiceModel || !fChoiceView || !fEditView) + 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); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index cf01dbbad1..216a2d7f78 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -39,13 +39,14 @@ public: virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); - virtual void EditViewStateChanged(); + virtual void EditViewStateChanged(bool updateChoices); private: BString fFullEnteredText; int32 fSelectedIndex; int32 fPatternStartPos; int32 fPatternLength; + bool fIgnoreEditViewStateChanges; }; diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 9f0a90b065..3f83e884d8 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -63,13 +63,17 @@ TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() } +// #pragma mark - + + TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, PatternSelector* patternSelector) : BAutoCompleter(new TextViewWrapper(textView), model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), - fTextView(textView) + fTextView(textView), + fModificationsReported(false) { fTextView->AddFilter(this); } @@ -81,6 +85,20 @@ TextViewCompleter::~TextViewCompleter() } +void +TextViewCompleter::SetModificationsReported(bool reported) +{ + fModificationsReported = reported; +} + + +void +TextViewCompleter::TextModified(bool updateChoices) +{ + EditViewStateChanged(updateChoices); +} + + filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { @@ -120,11 +138,13 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) return B_DISPATCH_MESSAGE; } default: - // dispatch message to textview manually... - Looper()->DispatchMessage(message, *target); - // ...and propagate the new state to the auto-completer: - EditViewStateChanged(); - return B_SKIP_MESSAGE; + 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; } - return B_DISPATCH_MESSAGE; } diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index a325603309..1a2955f6d7 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -22,6 +22,9 @@ public: PatternSelector* patternSelector = NULL); virtual ~TextViewCompleter(); + void SetModificationsReported(bool reported); + void TextModified(bool updateChoices); + private: virtual filter_result Filter(BMessage* message, BHandler** target); @@ -36,8 +39,10 @@ private: private: BTextView* fTextView; }; + private: BTextView* fTextView; + bool fModificationsReported; }; #endif // TEXT_CONTROL_COMPLETER_H From 37876e4b33ddb7258e98d6b5af42529f6dfc46b8 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 18:59:34 +0000 Subject: [PATCH 222/293] Extend the auto-completion framework in order to support using page-up/down to navigate the choices list. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@501 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleter.cpp | 30 +++++++++++ .../autocompletion/AutoCompleter.h | 5 ++ .../AutoCompleterDefaultImpl.cpp | 50 ++++++++++++++++--- .../autocompletion/AutoCompleterDefaultImpl.h | 7 +++ .../autocompletion/TextViewCompleter.cpp | 17 +++++++ 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index 2e5d45e164..09060512f6 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -158,6 +158,36 @@ BAutoCompleter::IsChoiceSelected() const } +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) { diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 16a94559b4..dab8268db2 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -83,6 +83,7 @@ public: = 0; virtual void HideChoices() = 0; virtual bool ChoicesAreShown() = 0; + virtual int32 CountVisibleChoices() const = 0; }; class CompletionStyle { @@ -97,6 +98,7 @@ public: 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; @@ -137,6 +139,9 @@ protected: 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(); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 5760852400..1f7f27c3ea 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -105,6 +105,13 @@ BDefaultCompletionStyle::IsChoiceSelected() const } +int32 +BDefaultCompletionStyle::SelectedChoiceIndex() const +{ + return fSelectedIndex; +} + + void BDefaultCompletionStyle::ApplyChoice(bool hideChoices) { @@ -187,13 +194,13 @@ BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices) // #pragma mark - BDefaultChoiceView::ListView -static const int32 BM_INVOKED = 'bmin'; +static const int32 MSG_INVOKED = 'invk'; BDefaultChoiceView::ListView::ListView( BAutoCompleter::CompletionStyle* completer) : - BListView(BRect(0,0,100,100), "ChoiceViewList"), + BListView(BRect(0, 0, 100, 100), "ChoiceViewList"), fCompleter(completer) { // we need to check if user clicks outside of window-bounds: @@ -205,7 +212,7 @@ void BDefaultChoiceView::ListView::AttachedToWindow() { SetTarget(this); - SetInvocationMessage(new BMessage(BM_INVOKED)); + SetInvocationMessage(new BMessage(MSG_INVOKED)); BListView::AttachedToWindow(); } @@ -221,7 +228,7 @@ void BDefaultChoiceView::ListView::MessageReceived(BMessage* message) { switch(message->what) { - case BM_INVOKED: + case MSG_INVOKED: fCompleter->ApplyChoice(); break; default: @@ -316,7 +323,8 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, BDefaultChoiceView::BDefaultChoiceView() : fWindow(NULL), - fListView(NULL) + fListView(NULL), + fMaxVisibleChoices(5) { } @@ -359,7 +367,7 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) fListView = new ListView(completer); int32 count = choiceModel->CountChoices(); - for(int32 i=0; iAddItem( new ListItem(choiceModel->ChoiceAt(i)) ); @@ -370,7 +378,7 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); fWindow->AddChild(fListView); - int32 visibleCount = min_c(count, 5); + int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; BRect pvRect = editView->GetAdjustmentFrame(); @@ -407,3 +415,31 @@ BDefaultChoiceView::ChoicesAreShown() return (fWindow != NULL); } + +int32 +BDefaultChoiceView::CountVisibleChoices() const +{ + return min_c(fMaxVisibleChoices, fListView->CountItems()); +} + + +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; +} + diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index 216a2d7f78..6c3e50e8f5 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -35,6 +35,7 @@ public: 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(); @@ -60,6 +61,7 @@ protected: virtual void MessageReceived(BMessage* msg); virtual void MouseDown(BPoint point); virtual void AttachedToWindow(); + private: BAutoCompleter::CompletionStyle* fCompleter; }; @@ -84,10 +86,15 @@ public: 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 diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 3f83e884d8..66e95e9ae6 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -122,6 +122,23 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) // 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_SKIP_MESSAGE; From 1f009b1e11c283ce1c13ce0c03d3b943c4015fb9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 19:13:58 +0000 Subject: [PATCH 223/293] Tweaked the delays for the auto-hiding of the mouse pointer and the interface in full-screen mode. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@502 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 49a0dc3a11..3ff7e2d9f3 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1904,7 +1904,7 @@ BrowserWindow::_CheckAutoHideInterface() _ShowInterface(true); else if (fNavigationGroup->IsVisible() && fLastMousePos.y > fNavigationGroup->Frame().bottom - && system_time() - fLastMouseMovedTime > 3000000) { + && system_time() - fLastMouseMovedTime > 1000000) { // NOTE: Do not re-use navigationGroupBottom in the above // check, since we only want to hide the interface when it is visible. _ShowInterface(false); From 402459960e49927432f8f7f9e6081b1f8d155d14 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 20:07:20 +0000 Subject: [PATCH 224/293] Fix empty URL input bar when switching to a tab after it loaded in the background. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@503 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3ff7e2d9f3..9888677abf 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -188,9 +188,9 @@ public: fURLInputContents = text; } - const char* URLInputContents() const + const BString& URLInputContents() const { - return fURLInputContents.String(); + return fURLInputContents; } void SetURLInputSelection(int32 selectionStart, int32 selectionEnd) @@ -946,7 +946,10 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) if (userData != NULL) { fURLInputGroup->SetPageIcon(userData->PageIcon()); - fURLInputGroup->SetText(userData->URLInputContents()); + if (userData->URLInputContents().Length()) + fURLInputGroup->SetText(userData->URLInputContents()); + else + fURLInputGroup->SetText(webView->MainFrameURL()); if (userData->URLInputSelectionStart() >= 0) { fURLInputGroup->TextView()->Select( userData->URLInputSelectionStart(), From af7e6dd1a4d25e5c44ebf550c03c149243a5e87f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:23:51 +0000 Subject: [PATCH 225/293] Display tool tips for browser tabs with the page title. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@504 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.h | 1 + src/apps/webpositive/tabview/TabManager.cpp | 21 +++++++++++++++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 23 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.h b/src/apps/webpositive/tabview/TabContainerView.h index 13815d1592..a5a7ee04fa 100644 --- a/src/apps/webpositive/tabview/TabContainerView.h +++ b/src/apps/webpositive/tabview/TabContainerView.h @@ -43,6 +43,7 @@ public: virtual void DoubleClickOutsideTabs() = 0; virtual void UpdateTabScrollability(bool canScrollLeft, bool canScrollRight) = 0; + virtual void SetToolTip(const BString& text) = 0; }; public: diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index bdde273b04..743b83916a 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -307,6 +307,17 @@ public: fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight); } + virtual void SetToolTip(const BString& text) + { + if (fCurrentToolTip == text) + return; + fCurrentToolTip = text; + fManager->GetTabContainerView()->HideToolTip(); + fManager->GetTabContainerView()->SetToolTip( + reinterpret_cast(NULL)); + fManager->GetTabContainerView()->SetToolTip(fCurrentToolTip.String()); + } + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -333,6 +344,7 @@ private: bool fCloseButtonsAvailable; BMessage* fDoubleClickOutsideTabsMessage; BMessenger fTarget; + BString fCurrentToolTip; }; @@ -502,6 +514,8 @@ WebTabView::MouseMoved(BPoint where, uint32 transit, } } + fController->SetToolTip(Label()); + TabView::MouseMoved(where, transit, dragMessage); } @@ -695,6 +709,13 @@ TabManager::TabGroup() const } +BView* +TabManager::GetTabContainerView() const +{ + return fTabContainerView; +} + + BView* TabManager::ContainerView() const { diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 04f86062a2..6558a1620f 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -58,6 +58,7 @@ public: #endif BView* TabGroup() const; + BView* GetTabContainerView() const; BView* ContainerView() const; BView* ViewForTab(int32 tabIndex) const; From f94d5e280024f8c54675efb36373b9357156eb41 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:41:36 +0000 Subject: [PATCH 226/293] Don't store the last window frame with the full-screen window size... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@505 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++++++- src/apps/webpositive/BrowserWindow.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b6f1cc349e..3e936e273f 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -253,7 +253,7 @@ BrowserApp::QuitRequested() if (!webWindow->Lock()) continue; if (webWindow->QuitRequested()) { - fLastWindowFrame = webWindow->Frame(); + fLastWindowFrame = webWindow->WindowFrame(); webWindow->Quit(); i--; } else { diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9888677abf..b3e88a54de 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -846,7 +846,7 @@ BrowserWindow::QuitRequested() _ShutdownTab(0); BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); + message.AddRect("window frame", WindowFrame()); be_app->PostMessage(&message); return true; } @@ -1018,6 +1018,16 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) } +BRect +BrowserWindow::WindowFrame() const +{ + if (fIsFullscreen) + return fNonFullscreenWindowFrame; + else + return Frame(); +} + + // #pragma mark - Notification API diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4fd972fcce..adbe3742a2 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -107,6 +107,8 @@ public: void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); + BRect WindowFrame() const; + private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, From e979801bf732ee2bab87b51fcce9a861a0d43043 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:52:34 +0000 Subject: [PATCH 227/293] Introduced --fullscreen and -f command line options. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@506 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 39 ++++++++++++------- src/apps/webpositive/BrowserApp.h | 9 +++-- src/apps/webpositive/BrowserWindow.cpp | 54 +++++++++++++------------- src/apps/webpositive/BrowserWindow.h | 2 + 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 3e936e273f..5f8972a5f4 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -102,6 +102,11 @@ 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; @@ -163,16 +168,15 @@ BrowserApp::ReadyToRun() fInitialized = true; int32 pagesCreated = 0; + bool fullscreen = false; if (fLaunchRefsMessage) { - _RefsReceived(fLaunchRefsMessage, &pagesCreated); + _RefsReceived(fLaunchRefsMessage, &pagesCreated, &fullscreen); delete fLaunchRefsMessage; - fLaunchRefsMessage = 0; - } - if (pagesCreated == 0) { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, - ""); - window->Show(); + fLaunchRefsMessage = NULL; } + if (pagesCreated == 0) + _CreateNewWindow("", fullscreen); + PostMessage(PRELOAD_BROWSING_HISTORY); } @@ -284,10 +288,15 @@ BrowserApp::QuitRequested() void -BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) +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); @@ -298,23 +307,25 @@ BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) continue; BString url; url << path.Path(); - _CreateNewPage(url); + _CreateNewPage(url, fullscreen); pagesCreated++; } BString url; for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) { - _CreateNewPage(url); + _CreateNewPage(url, fullscreen); pagesCreated++; } if (_pagesCreated != NULL) *_pagesCreated = pagesCreated; + if (_fullscreen != NULL) + *_fullscreen = fullscreen; } void -BrowserApp::_CreateNewPage(const BString& url) +BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) { uint32 workspace = 1 << current_workspace(); @@ -334,12 +345,12 @@ BrowserApp::_CreateNewPage(const BString& url) if (loadedInWindowOnCurrentWorkspace) return; } - _CreateNewWindow(url); + _CreateNewWindow(url, fullscreen); } void -BrowserApp::_CreateNewWindow(const BString& url) +BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen) { // Offset the window frame unless this is the first window created in the // session. @@ -350,6 +361,8 @@ BrowserApp::_CreateNewWindow(const BString& url) BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, url); + if (fullscreen) + window->ToggleFullscreen(); window->Show(); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index f83d379a63..1f48b9d947 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -54,9 +54,12 @@ public: private: void _RefsReceived(BMessage* message, - int32* pagesCreated = NULL); - void _CreateNewPage(const BString& url); - void _CreateNewWindow(const BString& url); + 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, diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b3e88a54de..b988105d4e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -674,7 +674,7 @@ BrowserWindow::MessageReceived(BMessage* message) break; case TOGGLE_FULLSCREEN: - _ToggleFullscreen(); + ToggleFullscreen(); break; case TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN: @@ -863,7 +863,7 @@ BrowserWindow::MenusBeginning() void BrowserWindow::Zoom(BPoint origin, float width, float height) { - _ToggleFullscreen(); + ToggleFullscreen(); } @@ -1028,6 +1028,31 @@ BrowserWindow::WindowFrame() const } +void +BrowserWindow::ToggleFullscreen() +{ + if (fIsFullscreen) { + MoveTo(fNonFullscreenWindowFrame.LeftTop()); + ResizeTo(fNonFullscreenWindowFrame.Width(), + fNonFullscreenWindowFrame.Height()); + + SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_DOCUMENT_WINDOW_LOOK); + + _ShowInterface(true); + } else { + fNonFullscreenWindowFrame = Frame(); + _ResizeToScreen(); + + SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_TITLED_WINDOW_LOOK); + } + fIsFullscreen = !fIsFullscreen; + fFullscreenItem->SetMarked(fIsFullscreen); + fToggleFullscreenButton->SetVisible(fIsFullscreen); +} + + // #pragma mark - Notification API @@ -1848,31 +1873,6 @@ BrowserWindow::_ShowPage(BWebView* view) } -void -BrowserWindow::_ToggleFullscreen() -{ - if (fIsFullscreen) { - MoveTo(fNonFullscreenWindowFrame.LeftTop()); - ResizeTo(fNonFullscreenWindowFrame.Width(), - fNonFullscreenWindowFrame.Height()); - - SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); - SetLook(B_DOCUMENT_WINDOW_LOOK); - - _ShowInterface(true); - } else { - fNonFullscreenWindowFrame = Frame(); - _ResizeToScreen(); - - SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); - SetLook(B_TITLED_WINDOW_LOOK); - } - fIsFullscreen = !fIsFullscreen; - fFullscreenItem->SetMarked(fIsFullscreen); - fToggleFullscreenButton->SetVisible(fIsFullscreen); -} - - void BrowserWindow::_ResizeToScreen() { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index adbe3742a2..16cb5d2b3d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -109,6 +109,8 @@ public: BRect WindowFrame() const; + void ToggleFullscreen(); + private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, From 86007edfa7722de33470ad300ae256c59f319bae Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 23:08:26 +0000 Subject: [PATCH 228/293] Use Cmd-J for hiding the downloads window. (Ticket #37) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@507 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 00d57dc50f..fc6fd0c3ce 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -156,7 +156,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, BMenu* menu = new BMenu("Downloads"); menu->AddItem(new BMenuItem("Open downloads folder", new BMessage(OPEN_DOWNLOADS_FOLDER))); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'J')); menuBar->AddItem(menu); fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); From 0953daf31f467e4938c1dcbc5708be73f71dd55e Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 17:59:00 +0000 Subject: [PATCH 229/293] "Manage Bookmarks" shortcut is now Cmd-M. Closed ticket #38. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@508 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b988105d4e..a2c8fb0ae1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -135,7 +135,7 @@ public: if (CountItems() > 0) AddItem(new BSeparatorItem(), 0); AddItem(new BMenuItem("Manage bookmarks", - new BMessage(SHOW_BOOKMARKS)), 0); + new BMessage(SHOW_BOOKMARKS), 'M'), 0); AddItem(new BMenuItem("Bookmark this page", new BMessage(CREATE_BOOKMARK), 'B'), 0); DoLayout(); From 795b44ebe65e6bc045f517773d0683b50a3baac1 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 18:49:18 +0000 Subject: [PATCH 230/293] F11 -> Toggle fullscreen F5 -> Reload page. (Ticket #56) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@509 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a2c8fb0ae1..d5b037fe3d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -506,6 +506,21 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; + } else if (bytes[0] == B_FUNCTION_KEY) { + // Some function key Firefox compatibility + int32 key; + if (message->FindInt32("key", &key) == B_OK) { + switch (key) { + case B_F5_KEY: + PostMessage(RELOAD); + break; + case B_F11_KEY: + PostMessage(TOGGLE_FULLSCREEN); + break; + default: + break; + } + } } else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the From 11365e77e8ba872f6f81353697d2101801d2cc76 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 19:31:56 +0000 Subject: [PATCH 231/293] Added Home button... by popular request. Will perhaps make it a setting. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@510 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/WebPositive.rdef | 13 +++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d5b037fe3d..09d90210c7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -83,6 +83,7 @@ enum { GO_BACK = 'goba', GO_FORWARD = 'gofo', STOP = 'stop', + HOME = 'home', GOTO_URL = 'goul', RELOAD = 'reld', CLEAR_HISTORY = 'clhs', @@ -359,6 +360,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->SetIcon(204); fStopButton->TrimIcon(); + fHomeButton = new IconButton("Home", 0, NULL, new BMessage(HOME)); + fHomeButton->SetIcon(206); + fHomeButton->TrimIcon(); + // URL input group fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); @@ -402,12 +407,14 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, // Navigation group BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(fBackButton, 0, 0) - .Add(fForwardButton, 1, 0) - .Add(fStopButton, 2, 0) - .Add(fURLInputGroup, 3, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fBackButton) + .Add(fForwardButton) + .Add(fStopButton) + .Add(fHomeButton) + .Add(fURLInputGroup) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, + kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) ; @@ -580,6 +587,9 @@ BrowserWindow::MessageReceived(BMessage* message) case STOP: CurrentWebView()->StopLoading(); break; + case HOME: + CurrentWebView()->LoadURL(fStartPageURL); + break; case CLEAR_HISTORY: { BrowsingHistory* history = BrowsingHistory::DefaultInstance(); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 16cb5d2b3d..6ef6f4d034 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -204,6 +204,7 @@ private: IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; + IconButton* fHomeButton; URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 5b89991cc9..c9561eebac 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -296,6 +296,19 @@ resource(204, "kActionStop") #'VICN' array { $"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, From 02a2ef19691fcce4fd29226eba6f315dc06296ba Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 19:57:34 +0000 Subject: [PATCH 232/293] * Small refactoring for retrieving the URL for a new tab. * Load new files into the current tab, if the URL of that tab is either empty or the URL for new tabs, instead of always opening a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@511 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 5 ++- src/apps/webpositive/BrowserWindow.cpp | 61 +++++++++++++++++--------- src/apps/webpositive/BrowserWindow.h | 3 ++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 5f8972a5f4..4efe1858e2 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -336,7 +336,10 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) continue; if (webWindow->Lock()) { if (webWindow->Workspaces() & workspace) { - webWindow->CreateNewTab(url, true); + if (webWindow->IsBlankTab()) + webWindow->CurrentWebView()->LoadURL(url); + else + webWindow->CreateNewTab(url, true); webWindow->Activate(); loadedInWindowOnCurrentWorkspace = true; } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 09d90210c7..33c347aa15 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -474,7 +474,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, + new BMessage(EDIT_HIDE_FIND_GROUP)); + // TODO: Should be a different shortcut, H is usually for Find selection. + AddShortcut('H', B_COMMAND_KEY, new BMessage(HOME)); // Add shortcuts to select a particular tab for (int32 i = 1; i <= 9; i++) { @@ -993,6 +996,17 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) } +bool +BrowserWindow::IsBlankTab() const +{ + if (CurrentWebView() == NULL) + return false; + BString requestedURL = CurrentWebView()->MainFrameRequestedURL(); + return requestedURL.Length() == 0 + || requestedURL == _NewTabURL(fTabManager->CountTabs() == 1); +} + + void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { @@ -1006,25 +1020,8 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->AddTab(webView, "New tab"); BString url(_url); - if (applyNewPagePolicy && url.Length() == 0) { - uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; - // Implement new page policy - switch (policy) { - case OpenStartPage: - url = fStartPageURL; - break; - case OpenSearchPage: - url = fSearchPageURL; - break; - case CloneCurrentPage: - if (CurrentWebView() != NULL) - url = CurrentWebView()->MainFrameURL(); - break; - case OpenBlankPage: - default: - break; - } - } + if (applyNewPagePolicy && url.Length() == 0) + url = _NewTabURL(isNewWindow); if (url.Length() > 0) webView->LoadURL(url.String()); @@ -1980,3 +1977,27 @@ BrowserWindow::_ShowInterface(bool show) fLoadingProgressBar->Hide(); } + +BString +BrowserWindow::_NewTabURL(bool isNewWindow) const +{ + BString url; + uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; + // Implement new page policy + switch (policy) { + case OpenStartPage: + url = fStartPageURL; + break; + case OpenSearchPage: + url = fSearchPageURL; + break; + case CloneCurrentPage: + if (CurrentWebView() != NULL) + url = CurrentWebView()->MainFrameURL(); + break; + case OpenBlankPage: + default: + break; + } + return url; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 6ef6f4d034..9e85994e51 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -104,6 +104,7 @@ public: virtual void SetCurrentWebView(BWebView* view); + bool IsBlankTab() const; void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); @@ -187,6 +188,8 @@ private: void _CheckAutoHideInterface(); void _ShowInterface(bool show); + BString _NewTabURL(bool isNewWindow) const; + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From fb03e2c5739385c47ec9fbdc7a2ffaab1d9ebc69 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 21 May 2010 16:59:58 +0000 Subject: [PATCH 233/293] * When downloads are still in progress, warn the user when the app quits and allow to continue downloading. * If the Downloads window is the only window, minimize on close instead of hiding without any way to get the window back. * Added menu item "New browser window" to Downloads window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@512 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 23 +++++++++++ src/apps/webpositive/DownloadWindow.cpp | 55 +++++++++++++++++++++++-- src/apps/webpositive/DownloadWindow.h | 4 ++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 4efe1858e2..79b2d3418e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -212,6 +212,7 @@ BrowserApp::MessageReceived(BMessage* message) } case WINDOW_OPENED: fWindowCount++; + fDownloadWindow->SetMinimizeOnClose(false); break; case WINDOW_CLOSED: fWindowCount--; @@ -250,6 +251,28 @@ BrowserApp::RefsReceived(BMessage* 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(window); if (!webWindow) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index fc6fd0c3ce..bd2c7e84c4 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -46,6 +46,7 @@ #include #include "BrowserApp.h" +#include "BrowserWindow.h" #include "DownloadProgressView.h" #include "SettingsKeys.h" #include "SettingsMessage.h" @@ -135,7 +136,8 @@ 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) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + fMinimizeOnClose(false) { SetPulseRate(1000000); @@ -156,6 +158,13 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, 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), 'J')); menuBar->AddItem(menu); @@ -305,12 +314,52 @@ DownloadWindow::MessageReceived(BMessage* message) bool DownloadWindow::QuitRequested() { - if (!IsHidden()) - Hide(); + 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( + 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 diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index e4e62bfecc..d76661ba4e 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -50,6 +50,9 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + bool DownloadsInProgress(); + void SetMinimizeOnClose(bool minimize); + private: void _DownloadStarted(BWebDownload* download); void _DownloadFinished(BWebDownload* download); @@ -66,6 +69,7 @@ private: BButton* fRemoveFinishedButton; BButton* fRemoveMissingButton; BString fDownloadPath; + bool fMinimizeOnClose; }; #endif // DOWNLOAD_WINDOW_H From 8a48f074d8c7c3c3b2b5b51e23e4d85132dec77b Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 21 May 2010 20:45:23 +0000 Subject: [PATCH 234/293] Handle B_RETURN and B_ESCAPE when the Find text control has focus. Refactored the code to visibly invoke a BButton and use it to show the respective buttons go down in the Find group. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@513 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 40 ++++++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 4 +++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 33c347aa15..b0f8ce1d23 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -390,16 +390,21 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindTextControl = new BTextControl("find", "Find:", "", new BMessage(EDIT_FIND_NEXT)); fFindTextControl->SetModificationMessage(new BMessage(FIND_TEXT_CHANGED)); + fFindPreviousButton = new BButton("Previous", + new BMessage(EDIT_FIND_PREVIOUS)); + fFindNextButton = new BButton("Next", new BMessage(EDIT_FIND_NEXT)); + fFindCloseButton = new BButton("Close", + new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(EDIT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(EDIT_FIND_NEXT))) + .Add(fFindPreviousButton) + .Add(fFindNextButton) .Add(fFindCaseSensitiveCheckBox) .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP))) + .Add(fFindCloseButton) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) @@ -538,11 +543,19 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) // when the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. - fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - fURLInputGroup->GoButton()->Invoke(); - snooze(1000); - fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); + _InvokeButtonVisibly(fURLInputGroup->GoButton()); + return; + } + } else if (target == fFindTextControl->TextView()) { + // Handle B_RETURN when the find text control has focus. + if (bytes[0] == B_RETURN) { + if ((modifiers & B_SHIFT_KEY) != 0) + _InvokeButtonVisibly(fFindPreviousButton); + else + _InvokeButtonVisibly(fFindNextButton); + return; + } else if (bytes[0] == B_ESCAPE) { + _InvokeButtonVisibly(fFindCloseButton); return; } } @@ -1978,6 +1991,17 @@ BrowserWindow::_ShowInterface(bool show) } +void +BrowserWindow::_InvokeButtonVisibly(BButton* button) +{ + button->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + button->Invoke(); + snooze(1000); + button->SetValue(B_CONTROL_OFF); +} + + BString BrowserWindow::_NewTabURL(bool isNewWindow) const { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9e85994e51..4097bbcdac 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -187,6 +187,7 @@ private: void _SetAutoHideInterfaceInFullscreen(bool doIt); void _CheckAutoHideInterface(); void _ShowInterface(bool show); + void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; @@ -220,6 +221,9 @@ private: BLayoutItem* fToggleFullscreenButton; BTextControl* fFindTextControl; + BButton* fFindPreviousButton; + BButton* fFindNextButton; + BButton* fFindCloseButton; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; From 3a3173e8cb42451fb9f99ea773b50085cfe5ba41 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 13:50:48 +0000 Subject: [PATCH 235/293] Set a tool-tip for the area outside of any tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@514 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index fc0f41b8bc..73457eaf5b 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -459,6 +459,11 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, fLastMouseEventTab = tab; if (fLastMouseEventTab) fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + else { + SetToolTip(static_cast(NULL)); + HideToolTip(); + SetToolTip("Double-click or middle-click to open new tab."); + } } } From 807ee4b4772640407e98deeab3f6f98a7a0805d6 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 13:51:29 +0000 Subject: [PATCH 236/293] Revert the default of the Auto-hide mouse pointer setting, by popular request. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@515 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- src/apps/webpositive/SettingsWindow.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b0f8ce1d23..d058e4e049 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -236,7 +236,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true), fAutoHideInterfaceInFullscreenMode(false), - fAutoHidePointer(true) + fAutoHidePointer(false) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8cfece44f9..79afb38ccc 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -335,7 +335,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) fAutoHidePointer = new BCheckBox("auto-hide pointer", B_TRANSLATE("Auto-hide mouse pointer."), new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED)); - fAutoHidePointer->SetValue(B_CONTROL_ON); + fAutoHidePointer->SetValue(B_CONTROL_OFF); BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -538,7 +538,7 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ( (fAutoHidePointer->Value() == B_CONTROL_ON) - != fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + != fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -671,7 +671,7 @@ SettingsWindow::_RevertSettings() fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); fAutoHidePointer->SetValue( - fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); From 82117cd7eb59625d0dfb0524dec5b00f618a81c0 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 19:04:46 +0000 Subject: [PATCH 237/293] Added "View->Page source" feature. For local files, it will open the file in the preferred app for text/x-source-code. For remote pages, it will save a temporary file and open the editor with that. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@517 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 97 ++++++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 3 + 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d058e4e049..9e527b4892 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -100,6 +100,8 @@ enum { TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN = 'tgah', CHECK_AUTO_HIDE_INTERFACE = 'cahi', + SHOW_PAGE_SOURCE = 'spgs', + EDIT_SHOW_FIND_GROUP = 'sfnd', EDIT_HIDE_FIND_GROUP = 'hfnd', EDIT_FIND_NEXT = 'fndn', @@ -315,9 +317,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, menu = new BMenu("View"); menu->AddItem(new BMenuItem("Reload", new BMessage(RELOAD), 'R')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(ZOOM_FACTOR_RESET), '0')); + menu->AddItem(new BMenuItem("Increase size", + new BMessage(ZOOM_FACTOR_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", + new BMessage(ZOOM_FACTOR_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", + new BMessage(ZOOM_FACTOR_RESET), '0')); fZoomTextOnlyMenuItem = new BMenuItem("Zoom text only", new BMessage(ZOOM_TEXT_ONLY)); fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); @@ -327,6 +332,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); + menu->AddItem(new BMenuItem("Page source", + new BMessage(SHOW_PAGE_SOURCE), 'U')); mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -347,7 +354,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->AddItem(bookmarkMenu); } - // Back, Forward & Stop + // Back, Forward, Stop & Home buttons fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); fBackButton->SetIcon(201); fBackButton->TrimIcon(); @@ -727,6 +734,13 @@ BrowserWindow::MessageReceived(BMessage* message) _CheckAutoHideInterface(); break; + case SHOW_PAGE_SOURCE: + CurrentWebView()->WebPage()->SendPageSource(); + break; + case B_PAGE_SOURCE_RESULT: + _HandlePageSourceResult(message); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -2025,3 +2039,78 @@ BrowserWindow::_NewTabURL(bool isNewWindow) const } return url; } + + +void +BrowserWindow::_HandlePageSourceResult(const BMessage* message) +{ + // TODO: This should be done in an extra thread perhaps. Doing it in + // the application thread is not much better, since it actually draws + // the pages... + + BPath pathToPageSource; + + BString url; + status_t ret = message->FindString("url", &url); + if (ret == B_OK && url.FindFirst("file://") == 0) { + // Local file + url.Remove(0, strlen("file://")); + pathToPageSource.SetTo(url.String()); + } else { + // Something else, store it. + // TODO: What if it isn't HTML, but for example SVG? + BString source; + ret = message->FindString("source", &source); + + if (ret == B_OK) + ret = find_directory(B_COMMON_TEMP_DIRECTORY, &pathToPageSource); + + BString tmpFileName("PageSource_"); + tmpFileName << system_time() << ".html"; + if (ret == B_OK) + ret = pathToPageSource.Append(tmpFileName.String()); + + BFile pageSourceFile(pathToPageSource.Path(), + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); + if (ret == B_OK) + ret = pageSourceFile.InitCheck(); + + if (ret == B_OK) { + ssize_t written = pageSourceFile.Write(source.String(), + source.Length()); + if (written != source.Length()) + ret = (status_t)written; + } + + if (ret == B_OK) { + const char* type = "text/html"; + size_t size = strlen(type); + pageSourceFile.WriteAttr("BEOS:TYPE", B_STRING_TYPE, 0, type, size); + // If it fails we don't care. + } + } + + entry_ref ref; + if (ret == B_OK) + ret = get_ref_for_path(pathToPageSource.Path(), &ref); + + if (ret == B_OK) { + BMessage refsMessage(B_REFS_RECEIVED); + ret = refsMessage.AddRef("refs", &ref); + if (ret == B_OK) { + ret = be_roster->Launch("text/x-source-code", &refsMessage); + if (ret == B_ALREADY_RUNNING) + ret = B_OK; + } + } + + if (ret != B_OK) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "Failed to show the " + "page source: %s\n", strerror(ret)); + BAlert* alert = new BAlert("Page source error", buffer, "OK"); + alert->Go(NULL); + } +} + + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4097bbcdac..67ac0f5311 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -191,6 +191,9 @@ private: BString _NewTabURL(bool isNewWindow) const; + void _HandlePageSourceResult( + const BMessage* message); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From a933ccf28dc6f4be8996b43b90b1a6ae4d64bfa3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 23 May 2010 12:56:24 +0000 Subject: [PATCH 238/293] When a download starts, do not start node monitoring the path while it is still pointing to the containing folder. Fixes ticket #62. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@518 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index f0c4e5bb3b..ad02111a05 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -308,14 +308,18 @@ DownloadProgressView::SaveSettings(BMessage* archive) void DownloadProgressView::AttachedToWindow() { - if (fDownload) + 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); - - BEntry entry(fPath.Path()); - if (entry.Exists()) - _StartNodeMonitor(entry); } From 4a09831444efe276c2186c9158951577e58472cb Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 23 May 2010 13:21:43 +0000 Subject: [PATCH 239/293] When the expected size of a download is unknown, at least set the progress bar to 100% when it finished. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@519 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index ad02111a05..f819651f72 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -372,7 +372,7 @@ DownloadProgressView::MessageReceived(BMessage* message) = fProcessStartTime = fLastSpeedReferenceTime = fEstimatedFinishReferenceTime = system_time(); break; - }; + } case B_DOWNLOAD_PROGRESS: { int64 currentSize; @@ -383,6 +383,12 @@ DownloadProgressView::MessageReceived(BMessage* message) } 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! @@ -414,12 +420,6 @@ DownloadProgressView::MessageReceived(BMessage* message) // TOAST! return; } - 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 B_NODE_MONITOR: { int32 opCode; @@ -610,6 +610,10 @@ 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)); From 591220f9b2c37416d9ec9ce244128967fa28296b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 30 May 2010 20:46:40 +0000 Subject: [PATCH 240/293] When disabling auto-hide, if the interface was currently still hidden, it wouldn't be restored, Closes ticket #6098. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@521 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9e527b4892..4b6f347769 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1950,6 +1950,7 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) } else { delete fPulseRunner; fPulseRunner = NULL; + _ShowInterface(true); } } From ed0c70c14d54d2e70168fbdfda1168c25411214a Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 15:19:36 +0000 Subject: [PATCH 241/293] * Small cleanups. * Make sure that the BWebView for which a notification is received still exists. This affected only the title changed notification, for which this was already checked, and the icon received notification, which could actually lead to a crash if the tab was closed before receiving the notification. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@522 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 17 +++++++++++------ src/apps/webpositive/tabview/TabManager.cpp | 7 +++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b6f347769..5b11c79aca 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1245,12 +1245,12 @@ BrowserWindow::MainDocumentError(const BString& failingURL, void BrowserWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < fTabManager->CountTabs(); i++) { - if (fTabManager->ViewForTab(i) == view) { - fTabManager->SetTabLabel(i, title); - break; - } - } + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) + return; + + fTabManager->SetTabLabel(tabIndex, title); + if (view != CurrentWebView()) return; @@ -1261,6 +1261,11 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { + // The view may already be gone, since this notification arrives + // asynchronously. + if (!fTabManager->HasView(view)) + return; + _SetPageIcon(view, icon); } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 743b83916a..4a26c33271 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -746,6 +746,13 @@ TabManager::TabForView(const BView* containedView) const } +bool +TabManager::HasView(const BView* containedView) const +{ + return TabForView(containedView) >= 0; +} + + void TabManager::SelectTab(int32 tabIndex) { diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 6558a1620f..4ccc64d35e 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -63,6 +63,7 @@ public: 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); From d848a89394e95064164c94f55582b1179a8bf664 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 15:43:35 +0000 Subject: [PATCH 242/293] Changed download short cut from J to D, as all the rest of the shortcuts make more sense and don't necessarily follow Firefox conventions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@523 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++++++++++------ src/apps/webpositive/DownloadWindow.cpp | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5b11c79aca..d3d985f165 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -280,18 +280,24 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), + 'L')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), + 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Settings", new BMessage(SHOW_SETTINGS_WINDOW))); - BMenuItem* aboutItem = new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED)); + menu->AddItem(new BMenuItem("Downloads", + new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Settings", + new BMessage(SHOW_SETTINGS_WINDOW))); + BMenuItem* aboutItem = new BMenuItem("About", + new BMessage(B_ABOUT_REQUESTED)); menu->AddItem(aboutItem); aboutItem->SetTarget(be_app); menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + BMenuItem* quitItem = new BMenuItem("Quit", + new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); mainMenu->AddItem(menu); diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index bd2c7e84c4..6329cf3c45 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -165,7 +165,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, menu->AddItem(newWindowItem); newWindowItem->SetTarget(be_app); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'J')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'D')); menuBar->AddItem(menu); fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); From 054e7e4344d6f6c5fb5bde6052a420ad5c1c4ae2 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 16:02:50 +0000 Subject: [PATCH 243/293] Make sure the interface is showing when the menus are used (i.e. by invoking Cmd-Esc shortcut). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@524 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d3d985f165..dede2493c0 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -918,6 +918,7 @@ BrowserWindow::MenusBeginning() { _UpdateHistoryMenu(); _UpdateClipboardItems(); + _ShowInterface(true); } From fdd4f3bbb8025e3ace4756b836969a516267515e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 15 Jun 2010 21:24:07 +0000 Subject: [PATCH 244/293] Add the static items at Bookmark menu construction, so the shortcuts work even when the menu has never been opened yet. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@526 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index dede2493c0..cd02a496a9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -127,6 +127,10 @@ public: : BNavMenu(title, B_REFS_RECEIVED, target) { + // Add these items here already, so the shortcuts work even when + // the menu has never been opened yet. + _AddStaticItems(); + SetNavDir(navDir); } @@ -137,11 +141,17 @@ public: BNavMenu::AttachedToWindow(); if (CountItems() > 0) AddItem(new BSeparatorItem(), 0); + _AddStaticItems(); + DoLayout(); + } + +private: + void _AddStaticItems() + { AddItem(new BMenuItem("Manage bookmarks", new BMessage(SHOW_BOOKMARKS), 'M'), 0); AddItem(new BMenuItem("Bookmark this page", new BMessage(CREATE_BOOKMARK), 'B'), 0); - DoLayout(); } }; From ef6778d11e46ede4e674d30de71501627f90ad1f Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 4 Jul 2010 03:24:04 +0000 Subject: [PATCH 245/293] Fix building Web+ against updated locale kit (currently requires manually placing liblocalestub.a from Haiku's build tree) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@527 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 - src/apps/webpositive/BrowserApp.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 79b2d3418e..2afbab8045 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -71,7 +71,6 @@ BrowserApp::BrowserApp() fDownloadWindow(NULL), fSettingsWindow(NULL) { - be_locale->GetAppCatalog(&fAppCatalog); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 1f48b9d947..05885583f6 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -77,8 +77,6 @@ private: DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; - - BCatalog fAppCatalog; }; From aef38397d3d2704c80e471c92ce5d07dbf3624c2 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 01:13:07 +0000 Subject: [PATCH 246/293] Fix crash that occurred when hitting pgup/pgdn in the URL input without having the choice list visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@530 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleterDefaultImpl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 1f7f27c3ea..9a9925d8ed 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -419,7 +419,14 @@ BDefaultChoiceView::ChoicesAreShown() int32 BDefaultChoiceView::CountVisibleChoices() const { - return min_c(fMaxVisibleChoices, fListView->CountItems()); + if (fListView) + { + return min_c(fMaxVisibleChoices, fListView->CountItems()); + } + else + { + return 0; + } } From 7f88e2461b704a8d950fda6ab8a063cd7b9ad927 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 01:18:56 +0000 Subject: [PATCH 247/293] When asked to programmatically open a new URL (i.e. by being launched from another app), give the resulting web view input focus. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@531 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 2afbab8045..2782892c3f 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -363,6 +363,7 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) else webWindow->CreateNewTab(url, true); webWindow->Activate(); + webWindow->CurrentWebView()->MakeFocus(true); loadedInWindowOnCurrentWorkspace = true; } webWindow->Unlock(); From 0c938691153d71116baa8ddeaa6d40d9b4b4c9d9 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 03:04:21 +0000 Subject: [PATCH 248/293] Fix style violation. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@532 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/AutoCompleterDefaultImpl.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 9a9925d8ed..5c4d742aaf 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -420,13 +420,9 @@ int32 BDefaultChoiceView::CountVisibleChoices() const { if (fListView) - { return min_c(fMaxVisibleChoices, fListView->CountItems()); - } else - { return 0; - } } From 01abe0e23c8f9bef0af1239c5ecf4d9352786226 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Tue, 20 Jul 2010 19:02:13 +0000 Subject: [PATCH 249/293] Fix Web+ build for this morning's locale changes/cleanups. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@537 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 79afb38ccc..f0be0810c4 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include From e71c5717b1aa65043bbef09830a474257e05403b Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Jul 2010 12:05:26 +0000 Subject: [PATCH 250/293] Account for the fact that the visible frame of a tab is one pixel larger at the bottom. Will fix Haiku ticket #6383 when a new package is made available. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@539 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 73457eaf5b..483a692749 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -429,9 +429,14 @@ 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( - layout->ItemAt(i)); - if (item && item->IsVisible() && item->Frame().Contains(where)) + TabLayoutItem* item = dynamic_cast(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; From a4841f3a5de8c50f348a3a9212d3c152c8d8994b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Jul 2010 19:12:48 +0000 Subject: [PATCH 251/293] Apply patch by Matt Madia: Add the escape key as a shortcut to stop page loads. Closes ticket #6409. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@541 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index cd02a496a9..1bb698234a 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -544,6 +544,9 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; + } else if (bytes[0] == B_ESCAPE) { + PostMessage(STOP); + return; } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; @@ -2084,27 +2087,27 @@ BrowserWindow::_HandlePageSourceResult(const BMessage* message) // TODO: What if it isn't HTML, but for example SVG? BString source; ret = message->FindString("source", &source); - + if (ret == B_OK) ret = find_directory(B_COMMON_TEMP_DIRECTORY, &pathToPageSource); - + BString tmpFileName("PageSource_"); tmpFileName << system_time() << ".html"; if (ret == B_OK) ret = pathToPageSource.Append(tmpFileName.String()); - + BFile pageSourceFile(pathToPageSource.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); if (ret == B_OK) ret = pageSourceFile.InitCheck(); - + if (ret == B_OK) { ssize_t written = pageSourceFile.Write(source.String(), source.Length()); if (written != source.Length()) ret = (status_t)written; } - + if (ret == B_OK) { const char* type = "text/html"; size_t size = strlen(type); From a071b4d0417fbb6971696d8bd5c54b1c5738c9ab Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 18 Aug 2010 14:53:43 +0000 Subject: [PATCH 252/293] Adapt to recent layout API changes. (Untested) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@543 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ src/apps/webpositive/DownloadProgressView.cpp | 2 ++ src/apps/webpositive/SettingsWindow.cpp | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 1bb698234a..e74bcabc3b 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -431,6 +431,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) + .TopView() ; // Navigation group @@ -445,6 +446,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .TopView() ; // Status bar group @@ -456,6 +458,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) + .TopView() ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -466,6 +469,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) + .TopView() ; // Layout diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index f819651f72..7048e1d56a 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -266,12 +266,14 @@ DownloadProgressView::Init(BMessage* archive) 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); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index f0be0810c4..743b03570a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -365,6 +365,8 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) + + .TopView() ; view->SetName(B_TRANSLATE("General")); return view; @@ -422,6 +424,8 @@ SettingsWindow::_CreateFontsPage(float spacing) .Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13) .SetInsets(spacing, spacing, spacing, spacing) + + .View() ; view->SetName(B_TRANSLATE("Fonts")); return view; @@ -464,6 +468,8 @@ SettingsWindow::_CreateProxyPage(float spacing) .Add(BSpaceLayoutItem::CreateGlue()) .SetInsets(spacing, spacing, spacing, spacing) + + .TopView() ; view->SetName(B_TRANSLATE("Proxy server")); return view; From 0e126349915b259d217eacfd502c66061058f400 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 19 Aug 2010 00:51:51 +0000 Subject: [PATCH 253/293] Fix BrowserWindow to work with new layout changes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@544 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 33 ++++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e74bcabc3b..59c30af523 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -419,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindCloseButton = new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) @@ -431,12 +432,11 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) - .TopView() ; // Navigation group - BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL) + .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fBackButton) .Add(fForwardButton) .Add(fStopButton) @@ -446,19 +446,17 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .TopView() ; // Status bar group - BView* statusGroup = BGroupLayoutBuilder(B_VERTICAL) + BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fStatusText) .Add(fLoadingProgressBar, 0.2) .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) - .TopView() ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -466,14 +464,13 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); - BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) + BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) - .TopView() ; - + // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BLayoutBuilder::Group<>(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR .Add(menuBarGroup) #endif @@ -489,12 +486,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->SetViewColor(B_TRANSPARENT_COLOR); fURLInputGroup->MakeFocus(true); - - fMenuGroup = layoutItemFor(menuBarGroup); - fTabGroup = layoutItemFor(fTabManager->TabGroup()); - fNavigationGroup = layoutItemFor(navigationGroup); - fFindGroup = layoutItemFor(findGroup); - fStatusGroup = layoutItemFor(statusGroup); + + fMenuGroup = menuBarGroup; + fTabGroup = fTabManager->TabGroup()->GetLayout(); + fNavigationGroup = navigationGroup; + fFindGroup = findGroup; + fStatusGroup = statusGroup; fToggleFullscreenButton = layoutItemFor(toggleFullscreenButton); fFindGroup->SetVisible(false); From 26bc1632000d90f95e6aaef5f468c735c5370ed6 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 9 Dec 2010 21:50:56 +0000 Subject: [PATCH 254/293] Layout fixes that hadn't yet been committed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@548 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 4 ++-- src/apps/webpositive/BrowserWindow.cpp | 8 ++++---- src/apps/webpositive/DownloadWindow.cpp | 6 +++--- src/apps/webpositive/URLInputGroup.cpp | 2 +- src/apps/webpositive/tabview/TabContainerView.cpp | 2 +- src/apps/webpositive/tabview/TabManager.cpp | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index 8d81bbb311..7dcc55260f 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -136,9 +136,9 @@ bool AuthenticationPanel::getAuthentication(const BString& text, m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials); // create layout - SetLayout(new BGroupLayout(B_VERTICAL)); + SetLayout(new BGroupLayout(B_VERTICAL, 0.0)); float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0) .Add(BGridLayoutBuilder(0, spacing) .Add(textView, 0, 0, 2) .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 1) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 59c30af523..643c20ad26 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -420,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindCloseButton = new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) @@ -435,7 +435,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Navigation group - BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fBackButton) .Add(fForwardButton) @@ -449,7 +449,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Status bar group - BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fStatusText) @@ -470,7 +470,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Layout - AddChild(BLayoutBuilder::Group<>(B_VERTICAL) + AddChild(BLayoutBuilder::Group<>(B_VERTICAL, 0.0) #if !INTEGRATE_MENU_INTO_TAB_BAR .Add(menuBarGroup) #endif diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 6329cf3c45..859722df47 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -66,7 +66,7 @@ class DownloadsContainerView : public BGroupView { public: DownloadsContainerView() : - BGroupView(B_VERTICAL) + BGroupView(B_VERTICAL, 0.0) { SetFlags(Flags() | B_PULSE_NEEDED); SetViewColor(245, 245, 245); @@ -149,7 +149,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, downloadPath.Path()); settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath); - SetLayout(new BGroupLayout(B_VERTICAL)); + SetLayout(new BGroupLayout(B_VERTICAL, 0.0)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); fDownloadViewsLayout = downloadsGroupView->GroupLayout(); @@ -180,7 +180,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, const float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0) .Add(menuBar) .Add(fDownloadsScrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index e5d5c9ecb3..f84f0e12bf 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -540,7 +540,7 @@ private: URLInputGroup::URLInputGroup(BMessage* goMessage) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fWindowActive(false) { GroupLayout()->SetInsets(2, 2, 2, 2); diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 483a692749..a95136a508 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -49,7 +49,7 @@ static const float kLeftTabInset = 4; TabContainerView::TabContainerView(Controller* controller) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fLastMouseEventTab(NULL), fMouseDown(false), fClickCount(0), diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 4a26c33271..7ab8066436 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -197,7 +197,7 @@ class TabContainerGroup : public BGroupView { public: TabContainerGroup(TabContainerView* tabContainerView) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fTabContainerView(tabContainerView), fScrollLeftTabButton(NULL), fScrollRightTabButton(NULL) @@ -263,7 +263,7 @@ class TabButtonContainer : public BGroupView { public: TabButtonContainer() : - BGroupView(B_HORIZONTAL) + BGroupView(B_HORIZONTAL, 0.0) { SetFlags(Flags() | B_WILL_DRAW); SetViewColor(B_TRANSPARENT_COLOR); From 8c15e2338555542ec1f90471e3b39fab287cc7b3 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 07:36:07 +0000 Subject: [PATCH 255/293] Set the tab label to the URL if no title is provided in the HTML. Fixes #6330. And so I'm back on Web+ development. Yay. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@549 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ src/apps/webpositive/tabview/TabManager.cpp | 9 +++++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 14 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 643c20ad26..9dc7430c68 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1246,6 +1246,10 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) NavigationCapabilitiesChanged(fBackButton->IsEnabled(), fForwardButton->IsEnabled(), false, view); + + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex > 0 && strcmp("New tab", fTabManager->TabLabel(tabIndex)) == 0) + fTabManager->SetTabLabel(tabIndex, url); } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 7ab8066436..3f364b652c 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -831,6 +831,15 @@ 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 ""; +} void TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 4ccc64d35e..97cd65c898 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -76,6 +76,7 @@ public: 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); From f0db6a3bb1b6908454fc8dd2e02867f65b885926 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 07:59:57 +0000 Subject: [PATCH 256/293] Don't try to load a blank URL for a new page. Fixes #6430. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@550 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 2782892c3f..653516f526 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -358,9 +358,10 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) continue; if (webWindow->Lock()) { if (webWindow->Workspaces() & workspace) { - if (webWindow->IsBlankTab()) - webWindow->CurrentWebView()->LoadURL(url); - else + if (webWindow->IsBlankTab()) { + if (url.Length() != 0) + webWindow->CurrentWebView()->LoadURL(url); + } else webWindow->CreateNewTab(url, true); webWindow->Activate(); webWindow->CurrentWebView()->MakeFocus(true); From 8ee88f9b6d32b6e6d03ac76feefda8d7f7bd8809 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 22:11:56 +0000 Subject: [PATCH 257/293] Show the status bar and therefore the progress bar even in fullscreen mode when a page is loading. Fixes #6086. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@551 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9dc7430c68..7d7d56a0b8 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1211,9 +1211,9 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) return; if (progress < 100 && fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Show(); + _ShowProgressBar(true); else if (progress == 100 && !fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Hide(); + _ShowProgressBar(false); fLoadingProgressBar->SetTo(progress); } @@ -2036,6 +2036,24 @@ BrowserWindow::_ShowInterface(bool show) } +void +BrowserWindow::_ShowProgressBar(bool show) +{ + if (show) { + if (!fStatusGroup->IsVisible() && (fVisibleInterfaceElements & INTERFACE_ELEMENT_STATUS) != 0) + fStatusGroup->SetVisible(true); + fLoadingProgressBar->Show(); + } else { + if (!fInterfaceVisible) + fStatusGroup->SetVisible(false); + // TODO: This is also used in _ShowInterface. Without it the status bar + // doesn't always hide again. It may be an Interface Kit bug. + while (!fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); + } +} + + void BrowserWindow::_InvokeButtonVisibly(BButton* button) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 67ac0f5311..e9f5fe3a6f 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -187,6 +187,7 @@ private: void _SetAutoHideInterfaceInFullscreen(bool doIt); void _CheckAutoHideInterface(); void _ShowInterface(bool show); + void _ShowProgressBar(bool); void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; From 290dc1146486029fd8c6de58dbdf327e0b8ee35f Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 17:08:35 +0000 Subject: [PATCH 258/293] Make the default location for the download window the lower right corner of screen, like NetPositive. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@554 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 653516f526..b9f905fb70 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -152,8 +152,15 @@ BrowserApp::ReadyToRun() #endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); + // Put download window in lower right of screen. 375 is about the minimum + // width with the default layout. + BRect defaultDownloadWindowFrame(0, 0, 375, 275); + BRect screenFrame = BScreen().Frame(); + // The extra 5 pixels is for the decorator frame + defaultDownloadWindowFrame.OffsetTo(screenFrame.Width() - defaultDownloadWindowFrame.Width() - 5, + screenFrame.Height() - defaultDownloadWindowFrame.Height() - 5); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", - BRect(100, 100, 300, 250)); + defaultDownloadWindowFrame); BRect settingsWindowFrame = fSettings->GetValue("settings window frame", BRect()); bool showDownloads = fSettings->GetValue("show downloads", false); From 8d1fc88170fd654a9ae84a6a41669221a5457abc Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 22:12:55 +0000 Subject: [PATCH 259/293] As indicated by Axel the border width for positioning the download window was hard-coded. This fixes that and refactors the code a bit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@555 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b9f905fb70..1504638ae7 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -152,13 +152,7 @@ BrowserApp::ReadyToRun() #endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); - // Put download window in lower right of screen. 375 is about the minimum - // width with the default layout. - BRect defaultDownloadWindowFrame(0, 0, 375, 275); - BRect screenFrame = BScreen().Frame(); - // The extra 5 pixels is for the decorator frame - defaultDownloadWindowFrame.OffsetTo(screenFrame.Width() - defaultDownloadWindowFrame.Width() - 5, - screenFrame.Height() - defaultDownloadWindowFrame.Height() - 5); + BRect defaultDownloadWindowFrame(-10, -10, 365, 265); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", defaultDownloadWindowFrame); BRect settingsWindowFrame = fSettings->GetValue("settings window frame", @@ -167,6 +161,17 @@ BrowserApp::ReadyToRun() 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)); From 530dea0f1619582b0246b5c7e1daad06e783b7ff Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 23:05:48 +0000 Subject: [PATCH 260/293] Let the controller handle setting the default tool tip for the tab bar so it knows the state changed. A good example of where using a controller-based design can't be done halfway. It took me way too long to debug this (that mostly being my fault.) Fixes #6382. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@556 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index a95136a508..d5269fd699 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -464,11 +464,8 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, fLastMouseEventTab = tab; if (fLastMouseEventTab) fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); - else { - SetToolTip(static_cast(NULL)); - HideToolTip(); - SetToolTip("Double-click or middle-click to open new tab."); - } + else + fController->SetToolTip("Double-click or middle-click to open new tab."); } } From 1526be737a797d99f96f8f85500deca19950047b Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 03:02:37 +0000 Subject: [PATCH 261/293] Add a stupidly simple "search Google from the URL bar" feature, a la Chrome. It still needs a lot but this doesn't seem to break anything and it already is making my browsing more productive. The hard-coding of Google will be fixed when some proper search engine provider handling is added. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@557 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 ++++++++++++++- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 7d7d56a0b8..e2db73b96d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -618,7 +618,10 @@ BrowserWindow::MessageReceived(BMessage* message) if (message->FindString("url", &url) != B_OK) url = fURLInputGroup->Text(); _SetPageIcon(CurrentWebView(), NULL); - CurrentWebView()->LoadURL(url.String()); + BString newUrl = _SmartURLHandler(url); + if (newUrl != url) + fURLInputGroup->TextView()->SetText(newUrl); + CurrentWebView()->LoadURL(newUrl.String()); break; } case GO_BACK: @@ -2090,6 +2093,16 @@ BrowserWindow::_NewTabURL(bool isNewWindow) const } +BString +BrowserWindow::_SmartURLHandler(const BString& url) const +{ + BString result = url; + if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) + result.Prepend("http://www.google.com/#q="); + return result; +} + + void BrowserWindow::_HandlePageSourceResult(const BMessage* message) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e9f5fe3a6f..fcae9d5f7b 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -191,6 +191,7 @@ private: void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; + BString _SmartURLHandler(const BString& url) const; void _HandlePageSourceResult( const BMessage* message); From c5efa2c0b94fafdec516818fb4ceb40a36fdc379 Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 05:03:13 +0000 Subject: [PATCH 262/293] Use the more conventional Google search URL, not the "Instant" one. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@558 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e2db73b96d..54a5be2885 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2098,7 +2098,7 @@ BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) - result.Prepend("http://www.google.com/#q="); + result.Prepend("http://www.google.com/search?q="); return result; } From ac09a4729657d4947422933153cf31a6ae9e27b0 Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 05:07:06 +0000 Subject: [PATCH 263/293] Make the max tab width always 300px instead of being proportional to the label text. I think a consistent tab size is more important. Also made the minimum a little smaller (60px.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@559 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabView.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabView.cpp b/src/apps/webpositive/tabview/TabView.cpp index bc5e2a6703..3bb78ec185 100644 --- a/src/apps/webpositive/tabview/TabView.cpp +++ b/src/apps/webpositive/tabview/TabView.cpp @@ -67,7 +67,7 @@ BSize TabView::MinSize() { BSize size(MaxSize()); - size.width = 100.0f; + size.width = 60.0f; return size; } @@ -83,8 +83,7 @@ BSize TabView::MaxSize() { float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); + float labelWidth = 300.0f; return BSize(labelWidth, _LabelHeight() + extra); } From 675a92e06038f86359f0ac69f24ba1d9886796dc Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 06:05:25 +0000 Subject: [PATCH 264/293] Implement http://webpositive.haiku-os.org/ticket/61 so that holding the command key and using the scroll wheel will zoom in and out. Also made it so that the scroll wheel only works when the mouse is over the view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@560 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 36 +++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 54a5be2885..f51f1f97c9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -533,16 +533,16 @@ void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { const char* bytes; - uint32 modifiers; + uint32 modifierKeys; if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK - && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { + && message->FindInt32("modifiers", (int32*)&modifierKeys) == B_OK) { - modifiers = modifiers & 0x000000ff; - if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) { + modifierKeys = modifierKeys & 0x000000ff; + if (bytes[0] == B_LEFT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_BACK); return; - } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { + } else if (bytes[0] == B_RIGHT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; } else if (bytes[0] == B_ESCAPE) { @@ -576,7 +576,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (target == fFindTextControl->TextView()) { // Handle B_RETURN when the find text control has focus. if (bytes[0] == B_RETURN) { - if ((modifiers & B_SHIFT_KEY) != 0) + if ((modifierKeys & B_SHIFT_KEY) != 0) _InvokeButtonVisibly(fFindPreviousButton); else _InvokeButtonVisibly(fFindNextButton); @@ -594,6 +594,30 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) fLastMouseMovedTime = system_time(); _CheckAutoHideInterface(); } + if (message->what == B_MOUSE_WHEEL_CHANGED) { + BPoint where; + uint32 buttons; + CurrentWebView()->GetMouse(&where, &buttons, false); + // Only do this when the mouse is over the web view + if (CurrentWebView()->Bounds().Contains(where)) { + // Zoom and unzoom text on Command + mouse wheel. + // This could of course (and maybe should be) implemented in the WebView, but there + // would need to be a way for the WebView to know the setting of the + // fZoomTextOnly member here. Plus other clients of the API may not want + // this feature. + if ((modifiers() & B_COMMAND_KEY) != 0) { + float dy; + if (message->FindFloat("be:wheel_delta_y", &dy) == B_OK) { + if (dy < 0) + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); + else + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); + return; + } + } + } else // Also don't scroll up and down if the mouse is not over the web view + return; + } BWebWindow::DispatchMessage(message, target); } From 36badc2d94f226f8c72178e62b8de8fef33ceba2 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 21:00:13 +0000 Subject: [PATCH 265/293] Add a scrollview (with associated resizing trickery to cut-off the sides of the scrollbar) to the auto-complete list. This now also makes the scrollwheel work but selection by mouse still needs implementing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@561 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleterDefaultImpl.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 5c4d742aaf..4bfd556175 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -10,6 +10,7 @@ #include #include +#include #include @@ -324,7 +325,7 @@ BDefaultChoiceView::BDefaultChoiceView() : fWindow(NULL), fListView(NULL), - fMaxVisibleChoices(5) + fMaxVisibleChoices(8) { } @@ -373,10 +374,12 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) ); } + BScrollView *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); - fWindow->AddChild(fListView); + fWindow->AddChild(scrollView); int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; @@ -390,8 +393,13 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) else listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); - fListView->MoveTo(0, 0); - fListView->ResizeTo(listRect.Width(), listRect.Height()); + // 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()); fWindow->MoveTo(listRect.left, listRect.top); fWindow->ResizeTo(listRect.Width(), listRect.Height()); fWindow->Show(); From 927bc248a345908efb52355296f9fb32eeb89325 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 22:08:08 +0000 Subject: [PATCH 266/293] Only use the scrollview if it is needed (to avoid the problem of a useless disabled scrollbar.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@562 94f232f2-1747-11df-bad5-a5bfde151594 --- .../AutoCompleterDefaultImpl.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 4bfd556175..0808239ef3 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -374,12 +374,18 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) ); } - BScrollView *scrollView = new BScrollView("", fListView, B_FOLLOW_NONE, 0, false, true, B_NO_BORDER); + 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); - fWindow->AddChild(scrollView); + if (scrollView != NULL) + fWindow->AddChild(scrollView); + else + fWindow->AddChild(fListView); int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; @@ -393,13 +399,18 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) else listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); - // 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()); + 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(); From a9112961b9f0b3fc1566eb58bc6fcc48c5fc94a5 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 22:51:13 +0000 Subject: [PATCH 267/293] Restore the original URL text when the escape key is pressed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@563 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/TextViewCompleter.cpp | 16 ++++++++++++++-- .../autocompletion/TextViewCompleter.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 66e95e9ae6..4e76f7255a 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -73,7 +73,8 @@ TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), fTextView(textView), - fModificationsReported(false) + fModificationsReported(false), + fOriginalTextSaved(false) { fTextView->AddFilter(this); } @@ -102,6 +103,11 @@ TextViewCompleter::TextModified(bool updateChoices) filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { + if (!fOriginalTextSaved) { + fOriginalText = fTextView->Text(); + fOriginalTextSaved = true; + } + const char* bytes; int32 modifiers; if (!target || message->FindString("bytes", &bytes) != B_OK @@ -140,7 +146,13 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) } case B_ESCAPE: - CancelChoice(); + if (fOriginalText != fTextView->Text()) { + fModificationsReported = false; + fTextView->SetText(fOriginalText.String()); + fTextView->SelectAll(); + fModificationsReported = true; + CancelChoice(); + } return B_SKIP_MESSAGE; case B_RETURN: if (IsChoiceSelected()) { diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index 1a2955f6d7..aeda86a7f0 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -43,6 +43,8 @@ private: private: BTextView* fTextView; bool fModificationsReported; + BString fOriginalText; + bool fOriginalTextSaved; }; #endif // TEXT_CONTROL_COMPLETER_H From a65490807d3c889418680b9c51d419ba78199736 Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 01:31:41 +0000 Subject: [PATCH 268/293] Mostly revert r563 and fix it properly. The ESC key should be dispatched to the text view from the filter as well as from the browser window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@564 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 +++++++--- .../autocompletion/TextViewCompleter.cpp | 18 +++--------------- .../autocompletion/TextViewCompleter.h | 2 -- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f51f1f97c9..fd2b2f49da 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Andrea Anzani - * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2007, 2010 Ryan Leavengood * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus * Copyright (C) 2010 Michael Lotz @@ -546,8 +546,12 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) PostMessage(GO_FORWARD); return; } else if (bytes[0] == B_ESCAPE) { - PostMessage(STOP); - return; + // Let the URL input handle escape when it is the target + if (target != fURLInputGroup->TextView()) { + // Otherwise do a stop + PostMessage(STOP); + return; + } } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 4e76f7255a..cdde7ffc66 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -73,8 +73,7 @@ TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), fTextView(textView), - fModificationsReported(false), - fOriginalTextSaved(false) + fModificationsReported(false) { fTextView->AddFilter(this); } @@ -103,11 +102,6 @@ TextViewCompleter::TextModified(bool updateChoices) filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { - if (!fOriginalTextSaved) { - fOriginalText = fTextView->Text(); - fOriginalTextSaved = true; - } - const char* bytes; int32 modifiers; if (!target || message->FindString("bytes", &bytes) != B_OK @@ -146,14 +140,8 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) } case B_ESCAPE: - if (fOriginalText != fTextView->Text()) { - fModificationsReported = false; - fTextView->SetText(fOriginalText.String()); - fTextView->SelectAll(); - fModificationsReported = true; - CancelChoice(); - } - return B_SKIP_MESSAGE; + CancelChoice(); + return B_DISPATCH_MESSAGE; case B_RETURN: if (IsChoiceSelected()) { ApplyChoice(); diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index aeda86a7f0..1a2955f6d7 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -43,8 +43,6 @@ private: private: BTextView* fTextView; bool fModificationsReported; - BString fOriginalText; - bool fOriginalTextSaved; }; #endif // TEXT_CONTROL_COMPLETER_H From 0afc39c5b1ee8f3d28ea45b0113206fc110697e7 Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 02:13:38 +0000 Subject: [PATCH 269/293] Ticket #69. Update the icon from tweaks made by Meanwhile. Thanks! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@565 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 389 +++++++++++++------------- 1 file changed, 193 insertions(+), 196 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index c9561eebac..9b475b34d1 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -49,202 +49,199 @@ resource vector_icon { $"37A9FFB9B9B904017E03FF360003FFFF0003FF9C0003FF000002010202BB36AE" $"BA1760B80FFF392B574ACCFB48652300000001FFFF0000013205400500030052" $"7502001002F8006BFF003E04006C050003900000020310020000006E00650400" - $"6B05000359463503C3A414039D816035000000000204BFC2B55BBBC5B55BC3BF" - $"B55BC6FABC93C6FAB896C6FAC090BFC2C3CBC3BFC3CBBBC5C3CBB88ABC93B88A" - $"C090B88AB896026EC5DCB8B6C713BAA0C4CAB706C110B579C307B5D5C0A2B565" - $"BFC2B55BC032B55BBDBCB55BBA69B7BABBC5B63AB8F9B94FB89DBD9CB84FBB7E" - $"B8C7BE9AB924BF77B8E0BEE7B9DEC11FBCE0C332BB38C279BEC5C405C2D8C31A" - $"C0FBC3FCC2C6C2C1C22FC2B7C27AC2BEC22FC2B7C227C2B7C227C2B7C227C2B7" - $"C241C2BDC241C2BDC206C2B0C199C2DBC1D0C2CBC159C2EEC0D4C2DDC115C2E5" - $"C051C2CEBF43C313BFB0C2B4BF3DC313BF36C313BF36C313BF36C313BF20C313" - $"BF20C313BF20C313BDEDC313BE23C313BDB9C2EDBD57C2DFBD87C2E3BD54C2DC" - $"BD3EC2C3BD3EC2C3BD31C2B4BD13C2A5BD26C2ABBD13C2A5BCA4C27EBCA4C27E" - $"BCA4C27EBC31C254BC31C254BC27C251BC12C24FBC1DC250BC10C24BBC0FC242" - $"BC11C246BC0FC242BBF5C219BBF5C219BBD3C1DEBB68C195BBAEC1A4BB71C16E" - $"BB58C129BB63C14EBB4BC101BB4BC0ADBB48C0D7BB4BC0ADBB4EC087BB4EC087" - $"BB52C054BB4DBFEEBB55C021BB9EBF93BBA9BEBFBBB0BF36BBA9BEBFBBA7BE93" - $"BBA7BE93BBA7BE53BBBCBE2FBBA8BE4BBBBCBE2FBBC7BE21BBC7BE21BC00BDD5" - $"BBE3BCFCBC5BBD3DBBE3BCFCBAB7BC58BAB7BC58BAB7BC58BA8BBC44BA90BC46" - $"BA8BBC44BA8BBC42BA8BBC42BA89BBEABA23BB79BA6ABBADBA23BB79BA12BB6B" - $"BA12BB6BBA12BB6BB9F8BB49B9F8BB49B9F8BB49B9AEBAF0B9AEBAF0B97EBAC3" - $"B928BAB1B950BAB5B924BAA9B91BBA9AB920BAA1B984BA6EB9DEB997B9B5B9F9" - $"B9F6B95DBA36B8F0BA0BB91FBA5EB8C4BA78B85EBA83B89EBACCB83DBB61B7E7" - $"BB18B813BB61B7E7BB6BB7E1BB6BB7E1BB6BB7E1BBFEB787BBFEB787BC65B74A" - $"BCB6B684BC94B6F6BCF5B68ABD58B665BD2DB67BBDA8B695BE6DB651BE29B697" - $"BE6FB650BE88B64FBE7CB64FBE62B6A0BEE1B72FBE88B70EBEE4B733BEE9B73E" - $"BEE5B73ABED8B744BEC6B74ABEC6B74ABEC6B74ABE75B7A5BE75B7A5BE63B7DD" - $"BE90B849BE74B817BE91B84CBE92B852BE92B852BE94B85CBE9DB87ABE97B86B" - $"BE94B884BE8CB88DBE8CB88DBE3AB8F0BD92B98FBDB7B906BD92B98FBD8DB9A1" - $"BD8DB9A1BD64B9D8BD7EBA55BD59BA19BD7BBA5CBD77BA63BD77BA63BD56BAA0" - $"BD4DBB2CBD39BAE6BD60BB70BDCCBBCEBD98BBA2BDFFBBFABE73BC3FBE33BC27" - $"BEBEBC5CBF5EBC42BF12BC56BF5EBC42BFAC37BFAC37BFD0BC1EC01CBC0FBFF5" - $"BC0BC046BC14C083BC4EC066BC35C04DBCD9C0F4BDDAC0B6BD63C0F4BDDAC107" - $"BDF9C102BDF2C0BABE84C127BF91C0B2BF1DC127BF91C133BF9DC133BF9DC131" - $"C00FC1C5C0F9C135C0D6C259C11CC348C059C2EEC0C9C348C059C36BC02FC36B" - $"C02FC36BC02FC388C019C388C019C3A8C003C3DBBFC5C3C9BFE8C3EEBFA0C409" - $"BF52C3F0BF73C409BF52C409BF53C409BF53C40DBF9AC495BFC1C450BFCEC4EB" - $"BFB3C542BF10C51FBF56C542BF10C551BEF2C551BEF2C551BEF2C555BEEBC555" - $"BEEBC57FBEA3C568BDFCC59EBE47C53ABDBBC4A3BDDFC4E1BDAAC4A3BDCAC4A3" - $"BDB5C4A3BDB5C4A3BDB5C4A5BD31C4A5BD31C4A8BD1EC4E8BCDFC4D2BCF5C4E8" - $"BCDFC4FEBCC9C4FEBCC9C4FEBCC9C516BCB3C516BCB3C545BC8BC582BC20C571" - $"BC5EC58CBC05C588BBBCC586BBD9C588BBBCC587BBA8C587BBA8C587BBA8C588" - $"BB9DC588BB9DC58DBB614EBAFAC584BB24C58ABADAC5C2BA5DC5B0BAA2C5C4BA" - $"62C5CBBA70C5CBBA70C5D9BA8EC60FBAD4C5EDBAB3C60ABB1FC648BBAAC627BB" - $"67C669BBEBC66FBC7BC670BC33C66FBC7BC672BCC4C672BCC4C674BCEAC66EBD" - $"37C678BD11C664BD5AC649BD9CC652BD79C633BDECC62CBE92C62DBE3FC621BE" - $"D5C67FBF2CC648BF16C750BD0F0006BC12B6E4BC12B6E4BC32B6B0BC55B638BC" - $"47B674BB81B6ABBA2BB802BAC4B747BA88B7E3BB30B77EBADDB7B0BB59B765BB" - $"AAB733BB82B74DBBCBB71DBC12B6E4BBFCB707BC12B6E4001DBACDBFD1BACDBF" - $"D1BAEBBFAABB29BF5CBB13BF89BB43BF24BB34BE93BB34BED0BB34BE4DBB60BD" - $"EABB34BE25BB80BDBEBBABBD60BBA1BD98BB48BD2ABA81BCBEBAE5BCF3BA67BC" - $"B1BA20BC83BA2DBCA0BA0FBC5BBA0DBC02BA1FBC28B9FEBBE5B9BABBB6B9D0BB" - $"D0B99BBB91B95FBB44B983BB66B93DBB24B8F0BB2DB91CBB16B8C0BB48B8BEBA" - $"DFB8C3BAFFB8B1BB14B89FBB7EB8A7BB49B8C9BB7EB8C5BBB2B8C3BB8AB8C6BB" - $"DBB8C9BC2EB8C7BC05B8D0BC40B8BABC49B8CBBC49B8B4BC4BB8AABC4EB8AFBC" - $"4DB8A0BC57B893BC4BB898BC56B882BC4AB88FBD10B88EBD00B893BD49B8E1BD" - $"E7B88DBE03B90DBE04B923BE75B906BE4BB946BEA8B985BF00B973BEC1B997BF" - $"3EB9A3BFC1B998BF81B9B0C011BA17C05FB9DBC02EBA25C0B3BA75C127BA3DC0" - $"E7BA8FC144BAC0C17FBAA9C160BAD8C19FBAFCC17CBAE4C19DBADDC13ABAD7C0" - $"A6BAD3C0EFBADBC061BACDBFD1BAEAC013BACDBFD10009BD5EB5D7BD5EB5D7BD" - $"81B5EEBDB1B60EBD84B605BDD0B613BE19B601BE01B61ABE55B5C3BEF6B5C4BE" - $"B0B5EFBF2DB5A2BFA3B55EBF5BB55EBFCEB55DC00CB58CBFE9B578C03CB5A7C0" - $"90B566C064B575BF3AB541BCA7B60EBDDDB57ABCECB623BD5EB5D7BD29B601BD" - $"5EB5D70005BF35B6EABF35B6EABF55B6ECBF9AB6F5BF7BB702BFCEB6E0BF87B6" - $"7DBF9CB693BF78B66DBF3CB664BF2FB623BF45B690BF35B6EABF6BB6CCBF35B6" - $"EA0004BA07B87FBA07B87FBA0CB868B9EFB850B9FEB85FB982B8E4B8F0BA35B9" - $"2CB988B97E31BA07B87FB974B8F0BA07B87F0066C6F7BC24C6F7BC24C6DCBB0A" - $"C6002FC68BB9F2C5B9B87CC4FFB79CC563B805C4CEB768C463B709C49AB737C4" - $"52B6FBC428B6EFC440B6E2C412B6FAC407B6C1C401B6D1C316B60FC0D0B56FC1" - $"F9B59AC0FBB58BC15FB59CC131B589C170B5A2C179B5C9C19FB5BDC12DB5E2C0" - $"8AB5C9C0D7B5C4C05AB5CDC03FB60EC043B5DDC03DB629C040B676C036B65DC0" - $"4BB694C0B6B65FC0A8B66FC0CDB643C0F1B61AC0B1B608C108B64BC0D0B6B1C1" - $"3AB6D6C0B5B6A7C066B689C083B67CC064B68AC05DB6AFC05FB6ABC053B6C0C0" - $"31B6D0C044B6CBBFE6B6E5BF94B741BFB0B6EFBF87B769BF5DB791BF88B781BF" - $"3BB79DBEF7B7B2BF17B7A4BECCB7C7BEFAB81CBEEAB7FFBF06B830BF19B86CBF" - $"03B860BF59B891BFBEB7E0BFA3B802BFE1B7B3C038B7ADC008B7BDC04FB7A6C0" - $"84B777C06CB76EC0D3B795C0F8B83EC0EBB7F4C110B83FC135B810C100B802C1" - $"0DB7E5C0ECB77043B7ABC125B795C15FB7FDC14DB7BDC170B83DC1C2B820C18E" - $"B860C1CFB813C1FDB7D5C1E2B7BDC214B7EAC1F1B838C215B82FC206B84BC23A" - $"B83DC222B843C25AB834C28BB842C26CB836C2AFB850C2FAB857C2D5B854C320" - $"B859C347B898C335B87BC377B8E7C24AB8C5C259B8C6C228B8C3C1E2B8D0C202" - $"B8C2C1C9B8DAC199B8F0C1B62FC179B8E5C13FB8B6C15BB8C8C118B89CC0C5B8" - $"72C0EFB885C07FB853BFE3B84FC02FB83FBFBFB856BF7FB87CBF9CB866BF5CB8" - $"97BF11B8A4BF35B87FBEDCB8DCBE6EB942BEB6B91FBE51B950BE19B976BE2EB9" - $"5CBE04B990BDF6B9D1BE04B9B4BDE9B9EEBDE2BA1DBDCAB9FCBDF8BA3CBDEFBA" - $"76BDFEBA53BDD9BAA9BDC9BB27BD9FBAEFBDF235BE71BBBCBE3ABB94BEAFBBE9" - $"BF41BBD2BEFBBBE5BF83BBC1C009BB9CBFC5BBA1C05FBB96C0DDBC03C0A1BBCD" - $"C104BC26C0F5BC67C114BC34C0D3BC9FC103BD00C0E8BCC8C11FBD37C159BDA3" - $"C13CBD6DC166BDBAC182BDE8C177BDD0C18EBE04C16DBE2DC17BBE15C152BE5E" - $"C13FBECFC13FBE97C13FBF0EC185BF4CC15DBF24C1AABF71C1A4BFE3C1A8BFB3" - $"C1A0C025C1DBC087C1B3C053C216C08AC289C06CC253C086C2CBC04DC319BFDE" - $"C2E8C00FC347BFB0C386BF66C378BFABC396BF13C3FEBEBFC3C2BEF2C435BE90" - $"C430BE0CC42EBE4DC432BDC0C433BD22C429BD6DC43CBCDEC4ABBC78C47EBCA7" - $"C4CDBC56C512BC03C505BC34C519BBE7C513BBA8C51336C513BB93C51135C51A" - $"BB71C4F8BB29C47EBB2CC48ABB5DC476BB0EC48BBB01C477BB14C4A1BAEDC478" - $"BACDC48BBAD8C442BAADC3F1BA66C418BA9AC3CCBA36C391B9CBC3AEBA00C389" - $"B9BEC36CB93BC342B92EC39AB94AC3E2B9A3C3C4B981C419B9DFC46DBA6AC44A" - $"BA20C46EBA73C496BA8AC48FBA85C4AFBA9CC4EABAA8C4CABAABC533BAA2C55A" - $"BA20C555BA61C562B9C7C4E8B9AFC51DB9DAC4CAB997C49EB958C4B6B975C48F" - $"B946C474B90EC466B92AC493B8F9C4BDB91DC49FB90BC4E0B932C52CB951C505" - $"B944C555B95EC5B4B96CC592B952C5C9B97CC5E7B9B8C5D9B9A2C5FEB9DCC627" - $"BA26C614BA00C645BA61C694BA9FC64DBA89C667BAE8C6B6BB83C693BB3FC6DF" - $"BBD4C6E3BC7CC6E4BC23C6E2BCCEC6D0BD79C6F5BD2CC6A7BDCCC69FBE9AC69F" - $"BE3EC6A1BE95C6A5BE88C6A3BE8DC6A2BE8FC6A1BEC0C696BEBEC6B2BEC4C6D6" - $"BE02C6D2BE15C6F6BD65C6F7BC24C700BCC4C6F7BC240008C301B7D8C301B7D8" - $"C2E6B7DCC2D4B7A4C2E8B7AEC2B1B792C269B7B8C288B7A7C204B7EFC236B743" - $"C221B77BC239B73AC285B744C27AB746C2A7B740C2F3B74FC2D8B731C30CB76B" - $"C33CB7A1C31FB787C360B7C2C301B7D8C31CB7D4C301B7D80004BB53C203BB53" - $"C203BB45C20DBB26C221BB38C21DBB55C249BBBAC291BB87C26EBB92C265BB53" - $"C203BB84C227BB53C2030005C4F4BE2EC4F4BE2EC4D3BE57C48CBEA4C4A6BE76" - $"C46EBEDAC47DBF53C47DBF18C4B6BF38C4EDBEB9C4D0BEECC502BE93C4F4BE2E" - $"C531BE48C4F4BE2E0009C213C327C213C327C17FC390BFF7C345C09DC332BFD0" - $"C349BF8EC36ABFACC350BF67C38CBF20C386BF56C386BEAFC386BDCDC386BE3E" - $"C386BEC1C3CBC0C0C3BABFC4C3DDC137C3AAC221C367C1AFC38EC22AC364C262" - $"C32BC280C337C249C322C213C327C22AC331C213C32702024E284E2C542E4C32" - $"4C30482E020250304C3252344C364E344C340202C951B81858305C3254365432" - $"4E300202583456365836563C5A3854380204BCD6C1F1BACDC370BEA5C09BC4A7" - $"BFA6C361BE3CC67FC1B1C065C5ADC23AC445BE91C715B827C85DB962C9B9B682" - $"C68C0204C3CFC072C309BF46C522C2743DC65FC0DEC4E4BC10C7F7B880C76BB8" - $"DAC831B842C6E2BC70C2E3B880C5CDBE43C189061EAEE6BAEAAAAF9A0EB9E5C6" - $"DFB9CC50B985C673BA12C5CDBAE4C593BA9EC0BFBC89BE0E36B8E6B993B8DA2E" - $"B874B92DB971B7B0BCD6BA52BCEFB87ABE3BB7AEBD62B7AEBF13B7AEBF862EBF" - $"93BA78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF" - $"A0BDCEBFCCC18BC1FDC323BF00C13E46C33BC197C43B46C3DCC12BC484C02CC4" - $"94C012C3EFC092C36FBE21C2BDBF40BC50C14BBBF74EBB8451BBE8C66FBA9EC6" - $"B90611AAAAA8BA02BBF0B9ECBB4ABAB8BCC9BB9DBCE2BE4EBB71C019BC7CC0A5" - $"BE08BF73BE6144BFA0BF6DBDDBC06CBD0245BCAFC1CABC30BF40BAABBE0EBB04" - $"BF0DBB04BD83BB04BD15BAB8BCAFBA38060BBAAA2A31C653BA0CC6C5BB84C646" - $"BB2BC69FBBB6C614BBB0C5A0BBDDC309BC1DC164BCAFC0CBBB71BFE6BAD8C0CB" - $"BACBC395BAE4C5C6060AAAAB0ABE47C125BF99C131BF80454448C1FDC395C21D" - $"C362C1C4C3F1C11EC448C052C494C02CC3EFC105C389BE67470605EA02BB37BA" - $"C5BBD7BA12B9ACB887B8E0B8ADB90BB86AB887B939B920B96C0A05C16BBB91C4" - $"74BB91C4DABC36C4A7BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF" - $"4DBA45BE0EBB04BEA7BB2BBD8ABAE3BD29BA520607AA3A39B8EDBE012F3CB99F" - $"3EB993BEDAB920BF99B946BE34B77BBFF6B7C339B74804032EBCE932BDCEBB2B" - $"BD34BB13BECDBB51BF4DBA380208CA68BA5FCB41BD02CA3AB9D0CA0FB6BCCAF4" - $"B7AEC947B5E955B58A55B58A55B58AC844B841C8FFB76C53B953C718B814C6E6" - $"B8FBC74BB728C5A02FC601B84FC2703DC646BCB6C5ADBC1DC712BD82C89DBEE7" - $"C79E40C89DBEE7060ABFFB0FC6F2C098C626BFCCC6F2BFCC5A345C3758315A2E" - $"5A305A2C582A562E582C54305230C692B854C692B920C692B7DAC53ABAAB4FB9" - $"ACC501BB1EC46EBBF7C4AEBB9DC3FBBCB6C56DBE0EC38FBE4EC64DBDF00207C8" - $"70BE74C870BE74C7A4BDA8C78BBB44C80BBB28C71835C633BBB7C6D5BBF0C5DB" - $"BB98C501BB44C50ABB7AC4F2BAEEC3F5BC43C43FBBD2C4B4BC83C6FF38C63336" - $"C7CB3AC83DBE9AC5B3BF8DC909BD020202C6392F4DB9F9C66CBAC54DBBE34FBB" - $"17C46EBAEB0202C969B7CEC967B916CAFFB9E2543654324E3002025834563658" - $"36C877BD8FC969BB84C7ABBBF70604EAC2BD4448C111C32FC07FC362C17EC33C" - $"C0E5C37CC1E40205C5ADB861C65F31C52CB75E50204E224E20C3E2BA5FC37CB9" - $"50C455BB91C606BD02C494BCB6C723BE0DCB1BBDA8CB97BDE4C79EBBF702044E" - $"B44BC4D4284EB5174BB9B9C408B8BAC43EBAD855BD4F4BBBD057BD4FC745BB77" - $"C818BC3C51BAC502034E28C4A1B847C53AB61650BA52C593B8A0C691BBAFC4E1" - $"BAAB59BD8FC4E1B7A104032EB77BC613B63CC969B50AC7ABB778CB36BCA9C99C" - $"04032EB966B906B953B7D4B8D3B86DB9C7B749BAB82C0406BE0BB689BE67B5FD" - $"C04CB608BF7FB5F1C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C3" - $"1EB70849B609C32304032EBDA8B887BEB4B76EBE11B775BFEC2BC059B8AD0403" - $"2E28BE01B3FFC0D8B4253FB3D3C288B5BDC2FC0406FE0BC79EBB2BC8F6BBAAC8" - $"41BB48C9ECBC2FCB27BDDBCB06BD15CB41BE74CA4FC07FCA99BFCBCA0FC118C9" - $"CFC27DCA0FC1E4C998C30058C3890A04C6FFBB11C857BC50C8BDBCC3C88ABD4F" - $"040CAAFABABC70C74BC092C699C303C5CDC3DBC54DC441C4CEC44EC382C1EAC3" - $"03C237C34DC1D5C2EEC05FC402C14AC3E0BF76C423BD88C461BD48C4FABE47C5" - $"14BE2E4DBE98C58CBDBBC5870608BAAABFECC1FD4448C1FDC395C21DC362C1C4" - $"C3F1C11EC448C052C494C02CC3EFC105C389BED4C2BD0A04C369BC83C6D838C6" - $"66BD1CC35CBD350A03B46542B4BE41B4BE420605AF03B6AFC969B63DC9F2B72F" - $"C8D0BE4155B821CA8EC11CC6FAC42EC5C6C560C53ABE67C91DC1E8C7EAB86DCB" - $"270604EEBFCCBB51C1FDBBD0C13EBC43C29FBB6FC18BBAAB43BB1EC146BAF2C0" - $"9ABB4B0A0430303050505050302C0A0001021240BAB100000000000040B755C6" - $"CCDBBE997901178300040A0101020240BAB100000000000040B755C6CCDBBE99" - $"790A0201030240BAB100000000000040B755C6CCDBBE99790A030A0506070809" - $"0A0C0D040B0240BAB100000000000040B755C6CCDBBE99790A11011312408447" - $"3AE65BBB0539406A8F40BD7AC6ED3001178400040A00012712401CCA00000000" - $"00004031D6BEA7B4C5651401178100040A150112024046733A7FB6BABB054015" - $"08437714C3BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF" - $"0A11011412402E52374883B74883402E5243A84DC5C35901178200040A160115" - $"02402E52374883B74883402E5243A84DC5C3590A17011602402E52374883B748" - $"83402E5243A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3" - $"590A17011802402E52374883B74883402E5243A84DC5C3590A1801190240268F" - $"36C1F1B73CD33FA9DD442903C369B00A1B011A02402E52374883B74883402E52" - $"43A84DC5C3590A2C011B02402E52374883B74883402E5243A84DC5C3590A1101" - $"1C12402E52374883B74883402E5243A84DC5C35901178100040A20011D124018" - $"A13C2DD3BC6F843F776243040C3B35B701178400040A28011D024018A13C481B" - $"BC6F843FA13143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0C" - $"BDA6830A2603212022023F94B53C057BBC14913F373546DE4E423FFC0A2B0122" - $"02401CCA000000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97" - $"FB40685AC6A141CA33220A0001291240075E0000000000004029CCC0DC88C59D" - $"5C01178100040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D011784" - $"00040A360124023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4" - $"F539818BBA43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A" - $"55C7EFC8485E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D2660117" - $"8200040A00012A12402E52374883B74883402E5241C554C5CE0401178100040A" - $"00012B12401CCA000000000000401CCAC0623FC4B46E01178100040A00012C12" - $"403196000000000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA00" - $"0000000000401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0" - $"E971C4B46E1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF" - $"0A3E01310240FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA00" - $"0000000000401CCAC0E971C42D3C01178200040A4001330A401CCA0000000000" - $"00401CCAC0E971C4B46E1DFF0A42013402360000000000000000360000489000" - $"4AE8000A420134023600000000000000003600004870004AE8000A4301340236" - $"00000000000000003600004850004AF8000A4301340236000000000000000036" - $"00004870004AF8000A430134023600000000000000003600004890004AF8000A" - $"44013402360000000000000000360000485000466000" + $"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 { From 1220bcc0af8ede85c24be8c80157861313fb0f6e Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 06:34:45 +0000 Subject: [PATCH 270/293] Add a setting to show or hide the Home button. I find it pretty useless myself. While I was able to add this fairly easily by cutting and pasting, it was still quite a bit of work. Seems like there should be a less-verbose way of doing this. But it did work the first time I tested, so I can't complain too much. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@566 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 8 ++++++++ src/apps/webpositive/SettingsKeys.cpp | 1 + src/apps/webpositive/SettingsKeys.h | 1 + src/apps/webpositive/SettingsWindow.cpp | 15 +++++++++++++++ src/apps/webpositive/SettingsWindow.h | 1 + 5 files changed, 26 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index fd2b2f49da..5a4de8c5d7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -387,6 +387,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fHomeButton = new IconButton("Home", 0, NULL, new BMessage(HOME)); fHomeButton->SetIcon(206); fHomeButton->TrimIcon(); + if (!fAppSettings->GetValue(kSettingsKeyShowHomeButton, true)) + fHomeButton->Hide(); // URL input group fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); @@ -929,6 +931,12 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyAutoHideInterfaceInFullscreenMode && message->FindBool("value", &flag) == B_OK) { _SetAutoHideInterfaceInFullscreen(flag); + } else if (name == kSettingsKeyShowHomeButton + && message->FindBool("value", &flag) == B_OK) { + if (flag) + fHomeButton->Show(); + else + fHomeButton->Hide(); } break; } diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 5bd2f32cb9..10208c8aff 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -33,6 +33,7 @@ const char* kSettingsKeyShowTabsIfSinglePageOpen 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"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 8f2b96de35..1a95bbfe89 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -34,6 +34,7 @@ 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; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 743b03570a..8b17a19f88 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -73,6 +73,7 @@ enum { 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', @@ -203,6 +204,7 @@ SettingsWindow::MessageReceived(BMessage* message) 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: @@ -338,6 +340,11 @@ SettingsWindow::_CreateGeneralPage(float spacing) 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) @@ -361,6 +368,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(fShowTabsIfOnlyOnePage) .Add(fAutoHideInterfaceInFullscreenMode) .Add(fAutoHidePointer) + .Add(fShowHomeButton) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -547,6 +555,9 @@ SettingsWindow::_CanApplySettings() const (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()); @@ -612,6 +623,8 @@ SettingsWindow::_ApplySettings() 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()); @@ -679,6 +692,8 @@ SettingsWindow::_RevertSettings() false)); fAutoHidePointer->SetValue( fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); + fShowHomeButton->SetValue( + fSettings->GetValue(kSettingsKeyShowHomeButton, true)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 9648860bff..251d84405a 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -98,6 +98,7 @@ private: BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; BCheckBox* fAutoHidePointer; + BCheckBox* fShowHomeButton; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 1af1ea854634d4b2c84bf0bc170a63b58a6269b5 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 5 Jan 2011 06:18:01 +0000 Subject: [PATCH 271/293] Implement #35: Add a tab menu. Still needs icons but this works for now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@569 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 4 + src/apps/webpositive/tabview/TabManager.cpp | 79 ++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index d5269fd699..52217fa9c7 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -330,6 +330,10 @@ TabContainerView::SelectTab(TabView* tab) if (fSelectedTab != NULL) index = GroupLayout()->IndexOfItem(tab->LayoutItem()); + if (!tab->LayoutItem()->IsVisible()) { + SetFirstVisibleTabIndex(index); + } + fController->TabSelected(index); } } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 3f364b652c..dc3fbb0251 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include @@ -184,12 +187,34 @@ public: 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_SCROLL_TABS_RIGHT = 'strt', + MSG_OPEN_TAB_MENU = 'otmn' }; @@ -200,7 +225,8 @@ public: BGroupView(B_HORIZONTAL, 0.0), fTabContainerView(tabContainerView), fScrollLeftTabButton(NULL), - fScrollRightTabButton(NULL) + fScrollRightTabButton(NULL), + fTabMenuButton(NULL) { } @@ -210,6 +236,8 @@ public: fScrollLeftTabButton->SetTarget(this); if (fScrollRightTabButton != NULL) fScrollRightTabButton->SetTarget(this); + if (fTabMenuButton != NULL) + fTabMenuButton->SetTarget(this); } virtual void MessageReceived(BMessage* message) @@ -223,6 +251,43 @@ public: 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 + tabMenu->InvalidateLayout(); + 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; @@ -241,6 +306,12 @@ public: 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); @@ -256,6 +327,7 @@ private: TabContainerView* fTabContainerView; TabButton* fScrollLeftTabButton; TabButton* fScrollRightTabButton; + TabMenuTabButton* fTabMenuButton; }; @@ -669,7 +741,8 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) NewTabButton* newTabButton = new NewTabButton(newTabMessage); newTabButton->SetTarget(be_app); fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); + fTabContainerGroup->AddTabMenuButton(new TabMenuTabButton( + new BMessage(MSG_OPEN_TAB_MENU))); } From 255cade7a020c9a71e4fd48579eb4d3f53d8e842 Mon Sep 17 00:00:00 2001 From: leavengood Date: Fri, 7 Jan 2011 21:07:08 +0000 Subject: [PATCH 272/293] Use the loader page in the settings directory which handles the case when no welcome page is installed (such as nightlies.) To do: not hard-coding the settings directory. Fixes Haiku bug #6869. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@572 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsKeys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 10208c8aff..b72166cd3a 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -43,7 +43,7 @@ const char* kSettingsKeySearchPageURL = "search page url"; const char* kDefaultDownloadPath = "/boot/home/Desktop/"; const char* kDefaultStartPageURL - = "file:///boot/system/documentation/welcome/welcome_en.html"; + = "file:///boot/home/config/settings/WebPositive/LoaderPages/Welcome"; const char* kDefaultSearchPageURL = "http://www.google.com"; const char* kSettingsKeyUseProxy = "use http proxy"; From 552778e90ca6fb2df4728cb2fe4d5279039980c3 Mon Sep 17 00:00:00 2001 From: leavengood Date: Fri, 7 Jan 2011 21:42:19 +0000 Subject: [PATCH 273/293] Align the tabs menu by using AttachedToWindow. Somewhat of a hack and I swear InvalidateLayout worked before, but it does not seem to now. Also use a const for an empty BString instead of returning a local for the tab label. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@573 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabManager.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index dc3fbb0251..f25b67769d 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -48,6 +48,9 @@ #include "TabView.h" +const static BString kEmptyString; + + // #pragma mark - Helper classes @@ -265,8 +268,9 @@ public: } } - // Force layout to get the final menu size - tabMenu->InvalidateLayout(); + // 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()); @@ -911,7 +915,7 @@ TabManager::TabLabel(int32 tabIndex) if (tab) return tab->Label(); else - return ""; + return kEmptyString; } void From 1ef6069fe4a9b07fd312bda1b70b796b09b4f762 Mon Sep 17 00:00:00 2001 From: phoudoin Date: Wed, 2 Mar 2011 18:15:57 +0000 Subject: [PATCH 274/293] Fix why escape wasn't closing the find panel as expected (#75). Fix fullscreen icon layout spacing issue (#76). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@576 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5a4de8c5d7..23e7973ee1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -466,11 +466,11 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); - BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL) + BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL, 0.0) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) ; - + // Layout AddChild(BLayoutBuilder::Group<>(B_VERTICAL, 0.0) #if !INTEGRATE_MENU_INTO_TAB_BAR @@ -488,7 +488,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->SetViewColor(B_TRANSPARENT_COLOR); fURLInputGroup->MakeFocus(true); - + fMenuGroup = menuBarGroup; fTabGroup = fTabManager->TabGroup()->GetLayout(); fNavigationGroup = navigationGroup; @@ -547,13 +547,6 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; - } else if (bytes[0] == B_ESCAPE) { - // Let the URL input handle escape when it is the target - if (target != fURLInputGroup->TextView()) { - // Otherwise do a stop - PostMessage(STOP); - return; - } } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; @@ -591,6 +584,10 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) _InvokeButtonVisibly(fFindCloseButton); return; } + } else if (bytes[0] == B_ESCAPE) { + // Default escape key behavior: + PostMessage(STOP); + return; } } if (message->what == B_MOUSE_MOVED || message->what == B_MOUSE_DOWN From 56b050f337f5cebf1fdd1a87047a0146c9c5a1a2 Mon Sep 17 00:00:00 2001 From: phoudoin Date: Thu, 10 Mar 2011 18:00:40 +0000 Subject: [PATCH 275/293] * Don't trust anymore provided MIME type (if any): use instead the registrar's type guessing feature, which we can (and should) trust way more. * Notify back the download objet when it's file location has changed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@577 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 7048e1d56a..7031e429c3 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -451,6 +451,7 @@ DownloadProgressView::MessageReceived(BMessage* message) 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]; @@ -474,6 +475,10 @@ DownloadProgressView::MessageReceived(BMessage* message) } } + // Inform download of the new path + if (fDownload) + fDownload->HasMovedTo(fPath); + float value = fStatusBar->CurrentValue(); fStatusBar->Reset(name); fStatusBar->SetTo(value); From c17922668baabee266ee2df0c10ecb2297355d6f Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 1 Jun 2011 20:06:11 +0000 Subject: [PATCH 276/293] Don't do the "smart URL handling" (also known as dumb URL handling) for file:// URLs. Fixes #7596. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@579 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 23e7973ee1..c0ed3abed9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2130,8 +2130,12 @@ BString BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; - if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) - result.Prepend("http://www.google.com/search?q="); + + // Only process if the URL is not for a local file + if (url.FindFirst("file://") == B_ERROR) { + if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) + result.Prepend("http://www.google.com/search?q="); + } return result; } From ae5b937ac2472a0d84c63a4ed5173cc2fae7ca13 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 1 Jun 2011 21:43:31 +0000 Subject: [PATCH 277/293] Make the check for URLs more generic before doing a search. Thanks for the suggestion mmlr. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@580 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c0ed3abed9..c0d5ce63ef 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2131,8 +2131,9 @@ BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; - // Only process if the URL is not for a local file - if (url.FindFirst("file://") == B_ERROR) { + // Only process if this doesn't look like a full URL (http:// or + // file://, etc.) + if (url.FindFirst("://") == B_ERROR) { if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) result.Prepend("http://www.google.com/search?q="); } From 6c086bdf6a4b39ff2300cb52ab6eff83d89c19af Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Mar 2012 02:19:48 +0000 Subject: [PATCH 278/293] Don't try to filter any of these keys if modifiers are pressed. Fixes Web+ eating things like the workspace switching shortcuts if the URL input group happened to have focus. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@585 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index cdde7ffc66..bed5ef0dd5 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -104,8 +104,9 @@ 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) { + if ((!target || message->FindString("bytes", &bytes) != B_OK + || message->FindInt32("modifiers", &modifiers) != B_OK) + || modifiers != 0) { return B_DISPATCH_MESSAGE; } From b4bab54a16381816e0f534b3d073a043aa74e13a Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Mar 2012 18:17:01 +0000 Subject: [PATCH 279/293] Be more specific about how we check the modifiers mask. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@586 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index bed5ef0dd5..48f7bcb4da 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -106,7 +106,8 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) int32 modifiers; if ((!target || message->FindString("bytes", &bytes) != B_OK || message->FindInt32("modifiers", &modifiers) != B_OK) - || modifiers != 0) { + || (modifiers & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY + | B_SHIFT_KEY)) != 0) { return B_DISPATCH_MESSAGE; } From a79446f47116535b146eaa022c4b6de4e01bb3ad Mon Sep 17 00:00:00 2001 From: aldeck Date: Tue, 1 May 2012 21:34:23 +0000 Subject: [PATCH 280/293] * B_TRANSLATE_CONTEXT is now B_TRANSLATION_CONTEXT as per the recent change in Haiku, cf. hrev44041 git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@587 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 4 ++-- src/apps/webpositive/support/FontSelectionView.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8b17a19f88..5a5ee41873 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -56,8 +56,8 @@ #include "WebSettings.h" -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "Settings Window" +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Settings Window" enum { MSG_APPLY = 'aply', diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 81ce76bcb0..d0df01baa1 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -26,8 +26,8 @@ #include -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "Font Selection view" +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Font Selection view" static const float kMinSize = 8.0; From 1ef59aee8ebaf0870fd60e4e66a60c116d2fb5a0 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:12:20 +0200 Subject: [PATCH 281/293] Add Jamfile for WebPositive --- src/apps/Jamfile | 1 + src/apps/webpositive/Jamfile | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/apps/webpositive/Jamfile diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 0d7b2f7519..13783d4521 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -60,4 +60,5 @@ HaikuSubInclude text_search ; HaikuSubInclude tracker ; HaikuSubInclude tv ; HaikuSubInclude webwatch ; +HaikuSubInclude webpositive ; HaikuSubInclude workspaces ; diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile new file mode 100644 index 0000000000..60febdd8d9 --- /dev/null +++ b/src/apps/webpositive/Jamfile @@ -0,0 +1,65 @@ +SubDir HAIKU_TOP src apps webpositive ; + +UseLibraryHeaders webkit ; + +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) ] ; +} + +# SVN revision +#local svnRevisionFile = [ FGristFiles svn_revision ] ; +#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ; +#CreateSVNRevisionFile $(svnRevisionFile) ; + +Application WebPositive : + # 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 + : + # webkit libs + javascriptcore webcore webkit wtf + # dependencies + curl icuuc icudata png sqlite3 xml2 z + # haiku + be bsd localestub network stdc++ tracker translation + : + WebPositive.rdef +; From 2ee4319d112fb910c9c90b7b0baec5e3828f0da0 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:26:13 +0200 Subject: [PATCH 282/293] Remove unneeded includes --- src/apps/webpositive/BrowserApp.cpp | 1 - src/apps/webpositive/BrowserWindow.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 1504638ae7..71e2177e42 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -26,7 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowserApp.h" #include "BrowserWindow.h" diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c0d5ce63ef..4987ea7f40 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -30,7 +30,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowserWindow.h" #include "AuthenticationPanel.h" From 7f21f81f4f3f268e34011a6f3a9f94022da93f65 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:31:18 +0200 Subject: [PATCH 283/293] Apply old patch by AnevilYak, fix BMenuField border drawing --- src/apps/webpositive/SettingsWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 5a5ee41873..66639f24b0 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -396,13 +396,13 @@ SettingsWindow::_CreateFontsPage(float spacing) fStandardSizesMenu = new BMenuField("standard font size", B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"), - NULL); + 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"), - NULL); + B_WILL_DRAW); _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -435,6 +435,7 @@ SettingsWindow::_CreateFontsPage(float spacing) .View() ; + view->SetName(B_TRANSLATE("Fonts")); return view; } @@ -469,7 +470,7 @@ SettingsWindow::_CreateProxyPage(float spacing) .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) ) From 08cada49a6f90a03657efa9fc3cba9110c9993fc Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:43:53 +0200 Subject: [PATCH 284/293] Apply old patch by AnevilYak, fix BMenuField border drawing Should have been part of the previous commit, sorry --- .../webpositive/support/FontSelectionView.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index d0df01baa1..be1adcbd5f 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -6,7 +6,7 @@ * Mark Hogben * DarkWyrm * Axel Dörfler, axeld@pinc-software.de - * Philippe Saint-Pierre, stpere@gmail.com + * Philippe Saint-Pierre, stpere@gmail.com * Stephan Aßmus */ @@ -59,14 +59,14 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, fFontsMenu = new BPopUpMenu("font menu"); // font menu - fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, NULL); + 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, NULL); + fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"), + fStylesMenu, B_WILL_DRAW); } else { fStylesMenu = NULL; fStylesMenuField = NULL; @@ -74,17 +74,17 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, // size menu fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu, - NULL); + 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.")); + "chars from A to Z.")); fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, - B_SIZE_UNLIMITED)); + B_SIZE_UNLIMITED)); fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.65)); fPreviewText->SetAlignment(B_ALIGN_RIGHT); @@ -351,35 +351,35 @@ FontSelectionView::UpdateFontsMenu() // #pragma mark - private -BLayoutItem* +BLayoutItem* FontSelectionView::CreateSizesLabelLayoutItem() { return fSizesMenuField->CreateLabelLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateSizesMenuBarLayoutItem() { return fSizesMenuField->CreateMenuBarLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateFontsLabelLayoutItem() { return fFontsMenuField->CreateLabelLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateFontsMenuBarLayoutItem() { return fFontsMenuField->CreateMenuBarLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateStylesLabelLayoutItem() { if (fStylesMenuField) @@ -388,7 +388,7 @@ FontSelectionView::CreateStylesLabelLayoutItem() } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateStylesMenuBarLayoutItem() { if (fStylesMenuField) @@ -484,7 +484,7 @@ FontSelectionView::_BuildSizesMenu() BMessage* message = new BMessage(kMsgSetSize); message->AddInt32("size", size); - message->AddString("name", Name()); + message->AddString("name", Name()); BMenuItem* item = new BMenuItem(label, message); if (size == fCurrentFont.Size()) From 79adea96897d45291ef5f98c07edac01007866fb Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:45:58 +0200 Subject: [PATCH 285/293] Fix src/apps/Jamfile alphabetical order Thanks augiedoggie --- src/apps/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 13783d4521..cd66b3e6c1 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -59,6 +59,6 @@ HaikuSubInclude terminal ; HaikuSubInclude text_search ; HaikuSubInclude tracker ; HaikuSubInclude tv ; -HaikuSubInclude webwatch ; HaikuSubInclude webpositive ; +HaikuSubInclude webwatch ; HaikuSubInclude workspaces ; From c4ba387bf8a43bca900c26e8af454a3df40b74c2 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 00:58:25 +0200 Subject: [PATCH 286/293] Adapt WebPositive build to make use of a webkit optional build package --- build/jam/OptionalBuildFeatures | 35 +++++++++++++++++++++++++++++++++ src/apps/webpositive/Jamfile | 26 +++++++++++++++--------- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 8cdc51972b..509e87f5d7 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -419,3 +419,38 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) { } } + +# WebKit +local webkitBaseURL = http://dude.uzzl.net/haiku ; +if $(TARGET_ARCH) = x86 { + if $(HAIKU_GCC_VERSION[1]) >= 4 { + HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ; + } else { + Echo "WebKit support not available on gcc $(HAIKU_GCC_VERSION[1])" ; + } + + local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE) + : $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ; + + HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) + $(HAIKU_WEBKIT_FILE:B) ] ; + + echo $(HAIKU_WEBKIT_DIR) ; + + 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)" ; +} diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile index 60febdd8d9..c1cb3b00a1 100644 --- a/src/apps/webpositive/Jamfile +++ b/src/apps/webpositive/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src apps webpositive ; -UseLibraryHeaders webkit ; +SubDirSysHdrs $(HAIKU_WEBKIT_HEADERS) ; SubDirC++Flags $(defines) -Wno-error=sequence-point ; SubDirCcFlags $(defines) -Wno-error=sequence-point ; @@ -17,12 +17,7 @@ for sourceDir in $(sourceDirs) { SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps webpositive $(sourceDir) ] ; } -# SVN revision -#local svnRevisionFile = [ FGristFiles svn_revision ] ; -#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ; -#CreateSVNRevisionFile $(svnRevisionFile) ; - -Application WebPositive : +local sources = # autocompletion AutoCompleter.cpp AutoCompleterDefaultImpl.cpp @@ -53,9 +48,22 @@ Application WebPositive : 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) : - # webkit libs - javascriptcore webcore webkit wtf + $(HAIKU_WEBKIT_LIBS) # dependencies curl icuuc icudata png sqlite3 xml2 z # haiku From 36aac7c55f78fdd6aae2dff8759150dd6d34dea6 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:15:26 +0200 Subject: [PATCH 287/293] Fix typo --- build/jam/FileRules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/FileRules b/build/jam/FileRules index 2a5b896000..86fbe8b2c6 100644 --- a/build/jam/FileRules +++ b/build/jam/FileRules @@ -199,7 +199,7 @@ rule ExtractArchive directory : entries : archiveFile : grist # and combo. # # - 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. # - The entries of the archive file one is interested in. The # rule always extracts the complete archive file, from the From 40c493ce343abb484c96f84e3ce7ca867b153bf6 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:18:37 +0200 Subject: [PATCH 288/293] Hardcode kSVNRevision = 0 until i adapt version tracking --- src/apps/webpositive/svn_revision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/svn_revision.cpp b/src/apps/webpositive/svn_revision.cpp index 489c64cdd4..9e415b5262 100644 --- a/src/apps/webpositive/svn_revision.cpp +++ b/src/apps/webpositive/svn_revision.cpp @@ -5,6 +5,6 @@ #include "svn_revision.h" -const int32 kSVNRevision = - #include "svn_revision" +const int32 kSVNRevision = 0; +// #include "svn_revision" ; From 69914905f5fb21097ba8856a119d821f9b6e0693 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:21:57 +0200 Subject: [PATCH 289/293] Remove left-over echo --- build/jam/OptionalBuildFeatures | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 509e87f5d7..1650242892 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -435,8 +435,6 @@ if $(TARGET_ARCH) = x86 { HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) $(HAIKU_WEBKIT_FILE:B) ] ; - echo $(HAIKU_WEBKIT_DIR) ; - HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR) : include/ : $(zipFile) : extracted-webkit ] ; From 8ae2b062a6a39fdbcb41fc6c2f75d30460b5f336 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:49:32 +0200 Subject: [PATCH 290/293] Fix control flow, stop if gcc < 4. Change package URL --- build/jam/OptionalBuildFeatures | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 1650242892..c29c74feed 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -421,34 +421,34 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) { # WebKit -local webkitBaseURL = http://dude.uzzl.net/haiku ; +local webkitBaseURL = http://haiku-files.org/files/optional-packages ; if $(TARGET_ARCH) = x86 { - if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ; - } else { + 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) ] ; + 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_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_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_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 ] ; + HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ; + } } else { Echo "WebKit support not available on $(TARGET_ARCH)" ; } From d061a7009519756006ab8b2430d17883765b43af Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 02:57:38 +0200 Subject: [PATCH 291/293] Fix WebPositive jamfile, cross building works --- src/apps/webpositive/Jamfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile index c1cb3b00a1..c13bb56bf9 100644 --- a/src/apps/webpositive/Jamfile +++ b/src/apps/webpositive/Jamfile @@ -64,10 +64,8 @@ Application WebPositive : $(sources) : $(HAIKU_WEBKIT_LIBS) - # dependencies - curl icuuc icudata png sqlite3 xml2 z - # haiku - be bsd localestub network stdc++ tracker translation + $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS) + be network tracker translation : WebPositive.rdef ; From 851c719d021e7f867be9f6dd97da23ce881b86ff Mon Sep 17 00:00:00 2001 From: Humdinger Date: Wed, 4 Jul 2012 08:42:38 +0200 Subject: [PATCH 292/293] Small text changes in alert when renaming/moving special folders. Since the button was renamed from "Do it!" to the specific action, an additional explanation in case of special user folders isn't needed any more. Split text into paragraphs for better readability. --- src/kits/tracker/FSUtils.cpp | 23 ++++++++++------------- src/kits/tracker/OpenWithWindow.cpp | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index ac2c1580e7..fb4e9d2fd0 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -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; } } diff --git a/src/kits/tracker/OpenWithWindow.cpp b/src/kits/tracker/OpenWithWindow.cpp index 464a1eeb47..9b9b8ac478 100644 --- a/src/kits/tracker/OpenWithWindow.cpp +++ b/src/kits/tracker/OpenWithWindow.cpp @@ -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.")); From eb971526498ad040cc8eb4b03ad439afb20d8f35 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Wed, 4 Jul 2012 20:37:22 -0400 Subject: [PATCH 293/293] Updated CARootCertificates. --- build/jam/OptionalPackages | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index c1639dfb28..926469fda5 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -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 ; }