add page manager

This commit is contained in:
clowwindy
2013-02-17 08:17:43 +08:00
parent 4aa89955fc
commit cb0e35a8e5
23 changed files with 4285 additions and 69 deletions

View File

@@ -11,18 +11,24 @@
621571AB16CF6BCB003D96B4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 621571AA16CF6BCB003D96B4 /* Foundation.framework */; };
621571AD16CF6BCB003D96B4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 621571AC16CF6BCB003D96B4 /* CoreGraphics.framework */; };
621571B316CF6BCB003D96B4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 621571B116CF6BCB003D96B4 /* InfoPlist.strings */; };
621571B516CF6BCB003D96B4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571B416CF6BCB003D96B4 /* main.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
621571B916CF6BCB003D96B4 /* SWBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571B816CF6BCB003D96B4 /* SWBAppDelegate.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
621571B516CF6BCB003D96B4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571B416CF6BCB003D96B4 /* main.m */; };
621571B916CF6BCB003D96B4 /* SWBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571B816CF6BCB003D96B4 /* SWBAppDelegate.m */; };
621571BB16CF6BCB003D96B4 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 621571BA16CF6BCB003D96B4 /* Default.png */; };
621571BD16CF6BCB003D96B4 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 621571BC16CF6BCB003D96B4 /* Default@2x.png */; };
621571BF16CF6BCB003D96B4 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 621571BE16CF6BCB003D96B4 /* Default-568h@2x.png */; };
621571C216CF6BCB003D96B4 /* SWBViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571C116CF6BCB003D96B4 /* SWBViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
621571C216CF6BCB003D96B4 /* SWBViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571C116CF6BCB003D96B4 /* SWBViewController.m */; };
621571DC16CF6D50003D96B4 /* SWBTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571D116CF6D50003D96B4 /* SWBTabView.m */; };
621571DD16CF6D50003D96B4 /* SWBTab.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571D316CF6D50003D96B4 /* SWBTab.m */; };
621571DE16CF6D50003D96B4 /* SWBTabBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571D516CF6D50003D96B4 /* SWBTabBarView.m */; };
621571DF16CF6D50003D96B4 /* SWBNewTabButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571D716CF6D50003D96B4 /* SWBNewTabButton.m */; };
621571E016CF6D50003D96B4 /* SWBSmallCloseButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571D916CF6D50003D96B4 /* SWBSmallCloseButton.m */; };
621571E116CF6D50003D96B4 /* SWBSmallCloseButtonHighlightView.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571DB16CF6D50003D96B4 /* SWBSmallCloseButtonHighlightView.m */; };
621571EA16CF74CC003D96B4 /* SWBWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571E616CF74CC003D96B4 /* SWBWebView.m */; };
621571EB16CF74CC003D96B4 /* SWBWebViewContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571E816CF74CC003D96B4 /* SWBWebViewContainer.m */; };
621571EF16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571EE16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.m */; };
621571F616CF7FA7003D96B4 /* SWBPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571F116CF7FA6003D96B4 /* SWBPage.m */; };
621571F716CF7FA7003D96B4 /* SWBPageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571F316CF7FA6003D96B4 /* SWBPageManager.m */; };
621571FC16CF7FE6003D96B4 /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 621571FB16CF7FE6003D96B4 /* JSONKit.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -53,6 +59,18 @@
621571D916CF6D50003D96B4 /* SWBSmallCloseButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SWBSmallCloseButton.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
621571DA16CF6D50003D96B4 /* SWBSmallCloseButtonHighlightView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SWBSmallCloseButtonHighlightView.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
621571DB16CF6D50003D96B4 /* SWBSmallCloseButtonHighlightView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SWBSmallCloseButtonHighlightView.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
621571E516CF74CC003D96B4 /* SWBWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SWBWebView.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
621571E616CF74CC003D96B4 /* SWBWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SWBWebView.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
621571E716CF74CC003D96B4 /* SWBWebViewContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SWBWebViewContainer.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
621571E816CF74CC003D96B4 /* SWBWebViewContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SWBWebViewContainer.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
621571ED16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SWBNetworkActivityIndicatorManager.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
621571EE16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = SWBNetworkActivityIndicatorManager.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
621571F016CF7FA6003D96B4 /* SWBPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWBPage.h; sourceTree = "<group>"; };
621571F116CF7FA6003D96B4 /* SWBPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWBPage.m; sourceTree = "<group>"; };
621571F216CF7FA6003D96B4 /* SWBPageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWBPageManager.h; sourceTree = "<group>"; };
621571F316CF7FA6003D96B4 /* SWBPageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWBPageManager.m; sourceTree = "<group>"; };
621571FA16CF7FE6003D96B4 /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = "<group>"; };
621571FB16CF7FE6003D96B4 /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -99,6 +117,9 @@
621571AE16CF6BCB003D96B4 /* ShadowWeb */ = {
isa = PBXGroup;
children = (
621571F916CF7FDB003D96B4 /* JSONKit */,
621571EC16CF7810003D96B4 /* Others */,
621571E216CF74BC003D96B4 /* WebView */,
621571CF16CF6D1F003D96B4 /* ToolBar */,
621571CE16CF6D19003D96B4 /* TabBar */,
621571B716CF6BCB003D96B4 /* SWBAppDelegate.h */,
@@ -150,6 +171,39 @@
name = ToolBar;
sourceTree = "<group>";
};
621571E216CF74BC003D96B4 /* WebView */ = {
isa = PBXGroup;
children = (
621571E516CF74CC003D96B4 /* SWBWebView.h */,
621571E616CF74CC003D96B4 /* SWBWebView.m */,
621571E716CF74CC003D96B4 /* SWBWebViewContainer.h */,
621571E816CF74CC003D96B4 /* SWBWebViewContainer.m */,
);
name = WebView;
sourceTree = "<group>";
};
621571EC16CF7810003D96B4 /* Others */ = {
isa = PBXGroup;
children = (
621571F016CF7FA6003D96B4 /* SWBPage.h */,
621571F116CF7FA6003D96B4 /* SWBPage.m */,
621571F216CF7FA6003D96B4 /* SWBPageManager.h */,
621571F316CF7FA6003D96B4 /* SWBPageManager.m */,
621571ED16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.h */,
621571EE16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.m */,
);
name = Others;
sourceTree = "<group>";
};
621571F916CF7FDB003D96B4 /* JSONKit */ = {
isa = PBXGroup;
children = (
621571FA16CF7FE6003D96B4 /* JSONKit.h */,
621571FB16CF7FE6003D96B4 /* JSONKit.m */,
);
name = JSONKit;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -225,6 +279,12 @@
621571DF16CF6D50003D96B4 /* SWBNewTabButton.m in Sources */,
621571E016CF6D50003D96B4 /* SWBSmallCloseButton.m in Sources */,
621571E116CF6D50003D96B4 /* SWBSmallCloseButtonHighlightView.m in Sources */,
621571EA16CF74CC003D96B4 /* SWBWebView.m in Sources */,
621571EB16CF74CC003D96B4 /* SWBWebViewContainer.m in Sources */,
621571EF16CF782C003D96B4 /* SWBNetworkActivityIndicatorManager.m in Sources */,
621571F616CF7FA7003D96B4 /* SWBPage.m in Sources */,
621571F716CF7FA7003D96B4 /* SWBPageManager.m in Sources */,
621571FC16CF7FE6003D96B4 /* JSONKit.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -307,6 +367,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ShadowWeb/ShadowWeb-Prefix.pch";
INFOPLIST_FILE = "ShadowWeb/ShadowWeb-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -319,6 +380,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "ShadowWeb/ShadowWeb-Prefix.pch";
INFOPLIST_FILE = "ShadowWeb/ShadowWeb-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};

214
ShadowWeb/JSONKit.h Normal file
View File

@@ -0,0 +1,214 @@
//
// JSONKit.h
// http://github.com/johnezang/JSONKit
// Licensed under the terms of the BSD License, as specified below.
//
/*
Copyright (c) 2011, John Engelhart
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the Zang Industries nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"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 THE COPYRIGHT
OWNER 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 <stddef.h>
#include <stdint.h>
#include <limits.h>
#include <TargetConditionals.h>
#include <AvailabilityMacros.h>
#ifdef __OBJC__
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSError.h>
#import <Foundation/NSObjCRuntime.h>
#import <Foundation/NSString.h>
#endif // __OBJC__
#ifdef __cplusplus
extern "C" {
#endif
// For Mac OS X < 10.5.
#ifndef NSINTEGER_DEFINED
#define NSINTEGER_DEFINED
#if defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
typedef long NSInteger;
typedef unsigned long NSUInteger;
#define NSIntegerMin LONG_MIN
#define NSIntegerMax LONG_MAX
#define NSUIntegerMax ULONG_MAX
#else // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
typedef int NSInteger;
typedef unsigned int NSUInteger;
#define NSIntegerMin INT_MIN
#define NSIntegerMax INT_MAX
#define NSUIntegerMax UINT_MAX
#endif // defined(__LP64__) || defined(NS_BUILD_32_LIKE_64)
#endif // NSINTEGER_DEFINED
#ifndef _JSONKIT_H_
#define _JSONKIT_H_
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__APPLE_CC__) && (__APPLE_CC__ >= 5465)
#define JK_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
#else
#define JK_DEPRECATED_ATTRIBUTE
#endif
#define JSONKIT_VERSION_MAJOR 1
#define JSONKIT_VERSION_MINOR 4
typedef NSUInteger JKFlags;
/*
JKParseOptionComments : Allow C style // and /_* ... *_/ (without a _, obviously) comments in JSON.
JKParseOptionUnicodeNewlines : Allow Unicode recommended (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}]) newlines.
JKParseOptionLooseUnicode : Normally the decoder will stop with an error at any malformed Unicode.
This option allows JSON with malformed Unicode to be parsed without reporting an error.
Any malformed Unicode is replaced with \uFFFD, or "REPLACEMENT CHARACTER".
*/
enum {
JKParseOptionNone = 0,
JKParseOptionStrict = 0,
JKParseOptionComments = (1 << 0),
JKParseOptionUnicodeNewlines = (1 << 1),
JKParseOptionLooseUnicode = (1 << 2),
JKParseOptionPermitTextAfterValidJSON = (1 << 3),
JKParseOptionValidFlags = (JKParseOptionComments | JKParseOptionUnicodeNewlines | JKParseOptionLooseUnicode | JKParseOptionPermitTextAfterValidJSON),
};
typedef JKFlags JKParseOptionFlags;
enum {
JKSerializeOptionNone = 0,
JKSerializeOptionPretty = (1 << 0),
JKSerializeOptionEscapeUnicode = (1 << 1),
JKSerializeOptionValidFlags = (JKSerializeOptionPretty | JKSerializeOptionEscapeUnicode),
};
typedef JKFlags JKSerializeOptionFlags;
#ifdef __OBJC__
typedef struct JKParseState JKParseState; // Opaque internal, private type.
// As a general rule of thumb, if you use a method that doesn't accept a JKParseOptionFlags argument, it defaults to JKParseOptionStrict
@interface JSONDecoder : NSObject {
JKParseState *parseState;
}
+ (id)decoder;
+ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (void)clearCache;
// The parse... methods were deprecated in v1.4 in favor of the v1.4 objectWith... methods.
- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length: instead.
- (id)parseUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithUTF8String:length:error: instead.
// The NSData MUST be UTF8 encoded JSON.
- (id)parseJSONData:(NSData *)jsonData JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData: instead.
- (id)parseJSONData:(NSData *)jsonData error:(NSError **)error JK_DEPRECATED_ATTRIBUTE; // Deprecated in JSONKit v1.4. Use objectWithData:error: instead.
// Methods that return immutable collection objects.
- (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
- (id)objectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
// The NSData MUST be UTF8 encoded JSON.
- (id)objectWithData:(NSData *)jsonData;
- (id)objectWithData:(NSData *)jsonData error:(NSError **)error;
// Methods that return mutable collection objects.
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length;
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(NSUInteger)length error:(NSError **)error;
// The NSData MUST be UTF8 encoded JSON.
- (id)mutableObjectWithData:(NSData *)jsonData;
- (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error;
@end
////////////
#pragma mark Deserializing methods
////////////
@interface NSString (JSONKitDeserializing)
- (id)objectFromJSONString;
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
- (id)mutableObjectFromJSONString;
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
@end
@interface NSData (JSONKitDeserializing)
// The NSData MUST be UTF8 encoded JSON.
- (id)objectFromJSONData;
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
- (id)mutableObjectFromJSONData;
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
@end
////////////
#pragma mark Serializing methods
////////////
@interface NSString (JSONKitSerializing)
// Convenience methods for those that need to serialize the receiving NSString (i.e., instead of having to serialize a NSArray with a single NSString, you can "serialize to JSON" just the NSString).
// Normally, a string that is serialized to JSON has quotation marks surrounding it, which you may or may not want when serializing a single string, and can be controlled with includeQuotes:
// includeQuotes:YES `a "test"...` -> `"a \"test\"..."`
// includeQuotes:NO `a "test"...` -> `a \"test\"...`
- (NSData *)JSONData; // Invokes JSONDataWithOptions:JKSerializeOptionNone includeQuotes:YES
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
- (NSString *)JSONString; // Invokes JSONStringWithOptions:JKSerializeOptionNone includeQuotes:YES
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
@end
@interface NSArray (JSONKitSerializing)
- (NSData *)JSONData;
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
- (NSString *)JSONString;
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
@end
@interface NSDictionary (JSONKitSerializing)
- (NSData *)JSONData;
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
- (NSString *)JSONString;
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
@end
#endif // __OBJC__
#endif // _JSONKIT_H_
#ifdef __cplusplus
} // extern "C"
#endif

3000
ShadowWeb/JSONKit.m Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,10 @@
#import <UIKit/UIKit.h>
#import "SWBNetworkActivityIndicatorManager.h"
#define appNetworkActivityIndicatorManager [(SWBAppDelegate *)[UIApplication sharedApplication].delegate networkActivityIndicatorManager]
@class SWBViewController;
@interface SWBAppDelegate : UIResponder <UIApplicationDelegate>
@@ -16,4 +20,6 @@
@property (strong, nonatomic) SWBViewController *viewController;
@property (nonatomic, strong) SWBNetworkActivityIndicatorManager *networkActivityIndicatorManager;
@end

View File

@@ -14,6 +14,9 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.networkActivityIndicatorManager = [[SWBNetworkActivityIndicatorManager alloc] init];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[SWBViewController alloc] init];
self.window.rootViewController = self.viewController;
@@ -31,6 +34,7 @@
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[((SWBViewController *) self.window.rootViewController) saveData];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
@@ -46,6 +50,7 @@
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[((SWBViewController *) self.window.rootViewController) saveData];
}
@end

View File

@@ -0,0 +1,18 @@
//
// SWBNetworkActivityIndicatorManager.h
// AquaWeb
//
// Created by clowwindy on 11-7-3.
// Copyright 2011年 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SWBNetworkActivityIndicatorManager : NSObject {
NSMutableSet *sources;
}
-(void)setSourceActivityStatusIsBusy:(id)source busy:(BOOL)busy;
@end

View File

@@ -0,0 +1,31 @@
//
// SWBNetworkActivityIndicatorManager.m
// AquaWeb
//
// Created by clowwindy on 11-7-3.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SWBNetworkActivityIndicatorManager.h"
@implementation SWBNetworkActivityIndicatorManager
- (id)init {
self = [super init];
if (self) {
sources = [[NSMutableSet alloc] init];
}
return self;
}
-(void)setSourceActivityStatusIsBusy:(id)source busy:(BOOL)busy {
if (busy&&![sources containsObject:source]) {
[sources addObject:source];
} else if([sources containsObject:source]){
[sources removeObject:source];
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:([sources count] > 0)];
}
@end

View File

@@ -76,16 +76,8 @@
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.highlighted) {
// radiusToDraw = radius * 1.0;
} else {
// radiusToDraw = radius;
}
//draw circle
// CGContextAddArc(context, width / 2, height / 2, radiusToDraw, 0, 2 * M_PI, 0);
CGFloat fillColor = self.highlighted ? kCrossPressedFillColor : kCrossFillColor;
CGFloat fillColorComponents[4] = {
fillColor, fillColor, fillColor, 1.0};

21
ShadowWeb/SWBPage.h Normal file
View File

@@ -0,0 +1,21 @@
//
// AQPage.h
// AquaWeb
//
// Created by clowwindy on 11-6-18.
// Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SWBPage : NSObject {
}
@property (nonatomic, strong) NSString * title;
@property (nonatomic, strong) NSString * url;
@property (nonatomic, strong) NSNumber * selected;
@property (nonatomic, assign) NSInteger tag; /* not saved into JSON */
@end

21
ShadowWeb/SWBPage.m Normal file
View File

@@ -0,0 +1,21 @@
//
// AQPage.m
// AquaWeb
//
// Created by clowwindy on 11-6-18.
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//
#import "SWBPage.h"
@implementation SWBPage
@synthesize title;
@synthesize url;
@synthesize selected;
@synthesize tag;
- (BOOL)isSelected {
return [self.selected boolValue];
}
@end

View File

@@ -0,0 +1,31 @@
//
// AQPageManager.h
// AquaWeb
//
// Created by clowwindy on 11-6-18.
// Copyright 2011年 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SWBPage.h"
@interface SWBPageManager : NSObject {
NSMutableArray *pages;
NSMutableDictionary *tagToPageMapping;
}
@property (nonatomic,readonly) NSArray *pages;
@property (nonatomic,readonly) NSMutableDictionary *tagToPageMapping;
@property (nonatomic,readonly) NSInteger selectedIndex;
-(SWBPage *)addPageWithTag:(NSInteger)tag;
-(void)removePage:(NSInteger)tag;
-(void)initMappingAndTabsByPages;
-(SWBPage *)pageByTag:(NSInteger)tag;
-(void)save;
-(void)load;
@end

115
ShadowWeb/SWBPageManager.m Normal file
View File

@@ -0,0 +1,115 @@
//
// AQPageManager.m
// AquaWeb
//
// Created by clowwindy on 11-6-18.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SWBPageManager.h"
#import "JSONKit.h"
//#import "AquaWebAppDelegate.h"
#define pageSavingDirectory [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define pageFilename [pageSavingDirectory stringByAppendingPathComponent:@"pages.json"]
@implementation SWBPageManager
@synthesize pages, tagToPageMapping;
- (id)init {
self = [super init];
if (self) {
pages = [[NSMutableArray alloc] init];
tagToPageMapping = [[NSMutableDictionary alloc] init];
}
return self;
}
-(SWBPage *)addPageWithTag:(NSInteger)tag {
// AQPage *page = [NSEntityDescription insertNewObjectForEntityForName:kAQPageClass inManagedObjectContext:objContext];
SWBPage *page = [[SWBPage alloc] init];
page.tag = tag;
[pages addObject:page];
[tagToPageMapping setValue:page forKey:[NSString stringWithFormat:@"%d", tag]];
return page;
}
-(void)removePage:(NSInteger)tag {
SWBPage *page = [self pageByTag:tag];
// [objContext deleteObject:page];
[pages removeObject:page];
[tagToPageMapping removeObjectForKey:[NSString stringWithFormat:@"%d", tag]];
}
-(void)initMappingAndTabsByPages {
[tagToPageMapping removeAllObjects];
NSUInteger count = [pages count];
for (int i = 0; i < count; i++) {
[tagToPageMapping setValue:[pages objectAtIndex:i] forKey:[NSString stringWithFormat:@"%d", i]];
}
}
-(SWBPage *)pageByTag:(NSInteger)tag {
return [tagToPageMapping valueForKey:[NSString stringWithFormat:@"%d", tag]];
}
-(void)save {
// NSError *error;
// [objContext save:&error];
NSMutableArray *data = [[NSMutableArray alloc] init];
for (SWBPage *page in pages) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:4];
[dict setObject:page.title forKey:@"title"];
[dict setObject:page.url forKey:@"url"];
[dict setObject:page.selected forKey:@"selected"];
[data addObject:dict];
}
NSString *content = [data JSONString];
NSError *error = nil;
[content writeToFile:pageFilename atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error != NULL) {
NSLog(@"%@", error);
}
}
-(void)load {
NSMutableArray *oldpages = [[NSMutableArray alloc] init];
NSError *error = nil;
NSString *content = [NSString stringWithContentsOfFile:pageFilename encoding:NSUTF8StringEncoding error:&error];
if (error == NULL) {
NSArray *data = [content objectFromJSONString];
for (NSDictionary *dict in data) {
SWBPage *page = [[SWBPage alloc] init];
page.title = [dict objectForKey:@"title"];
page.url = [dict objectForKey:@"url"];
page.selected = [dict objectForKey:@"selected"];
[oldpages addObject:page];
}
} else {
NSLog(@"%@", error);
}
if (oldpages != nil) {
for (SWBPage *page in oldpages) {
[pages addObject:page];
}
}
}
-(NSInteger)selectedIndex {
for (NSInteger i = 0; i < [pages count]; i++) {
if ([((SWBPage *)[pages objectAtIndex:i]).selected boolValue]) {
return i;
}
}
return 0;
}
@end

View File

@@ -16,7 +16,6 @@
- (id)initWithTag:(NSInteger)aTag;
@property (nonatomic, strong) NSString *title;
//@property (nonatomic, retain) NSURL *url;
@property (nonatomic, readonly) int tag;
@end

View File

@@ -18,10 +18,10 @@
@required
-(void)SWBTabBarViewNewTabButtonDidClick;
-(void)SWBTabBarViewTabDidClose:(SWBTab *)tab;
-(void)SWBTabBarViewTabDidMove:(SWBTab *)tab toIndex:(NSInteger)index;
-(void)SWBTabBarViewTabDidSelect:(SWBTab *)tab;
-(void)tabBarViewNewTabButtonDidClick;
-(void)tabBarViewTabDidClose:(SWBTab *)tab;
-(void)tabBarViewTabDidMove:(SWBTab *)tab toIndex:(NSInteger)index;
-(void)tabBarViewTabDidSelect:(SWBTab *)tab;
@end

View File

@@ -466,7 +466,7 @@
[self layoutTabsWithAction:SWBTabBarActionClose animated:YES];
[delegate SWBTabBarViewTabDidClose:tab];
[delegate tabBarViewTabDidClose:tab];
}
@@ -503,7 +503,7 @@
[self reorderTabViews];
if (newCurrentTab) {
[delegate SWBTabBarViewTabDidSelect:currentTab];
[delegate tabBarViewTabDidSelect:currentTab];
}
}
@@ -512,7 +512,7 @@
}
-(void)newTabButtonClicked {
[delegate SWBTabBarViewNewTabButtonDidClick];
[delegate tabBarViewNewTabButtonDidClick];
}
-(void)tabClicked:(id)sender {
@@ -520,7 +520,7 @@
self.currentTab = [self tabByTag:tabView.tag];
}
-(void)SWBTabViewDidClickCloseButton:(id)sender {
-(void)tabViewDidClickCloseButton:(id)sender {
SWBTabView *tabView = sender;
SWBTab *tab = [self tabByTag:tabView.tag];
[self closeTab:tab animated:YES];
@@ -581,7 +581,7 @@
[tabViews removeObject:tabView];
[tabViews insertObject:tabView atIndex:newIndex];
[delegate SWBTabBarViewTabDidMove:currentDraggingTab toIndex:newIndex];
[delegate tabBarViewTabDidMove:currentDraggingTab toIndex:newIndex];
}
[self layoutTabsWithAction:SWBTabBarActionDraggingTab animated:YES];
} else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
@@ -603,11 +603,6 @@
[self tabViewByTag:tag].title = theTitle;
}
//-(void)setPercentForTab:(NSInteger)tag percentage:(float)percentage {
// [self tabViewByTag:tag].percentage = percentage;
//
//}
-(void)setLoadingForTab:(NSInteger)tag loading:(BOOL)loading {
[self tabViewByTag:tag].loading = loading;

View File

@@ -13,23 +13,19 @@
@required
-(void) SWBTabViewDidClickCloseButton:(id)sender;
-(void) tabViewDidClickCloseButton:(id)sender;
@end
@interface SWBTabView : UIControl {
// CGFloat gradTopColor;
// CGFloat gradBottomColor;
SWBSmallCloseButton *closeButton;
UILabel *titleLabel;
// UIProgressView *progressView;
UIActivityIndicatorView *indicatorView;
}
@property (nonatomic, assign) BOOL focused;
@property (nonatomic, weak) id<SWBTabViewDelegate> delegate;
@property (nonatomic, strong) IBOutlet NSString *title;
//@property (nonatomic, assign) float percentage;
@property (nonatomic, assign) BOOL loading;
@property (weak, nonatomic, readonly) UILabel *titleLabel;

View File

@@ -18,7 +18,7 @@
@synthesize loading;
-(void)closeButtonDidClick {
[self.delegate SWBTabViewDidClickCloseButton:self];
[self.delegate tabViewDidClickCloseButton:self];
}
-(void) loadDefaults {
@@ -35,54 +35,25 @@
// title label
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 8, self.bounds.size.width - 70, 21)];
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight
// |UIViewAutoresizingFlexibleBottomMargin
// | UIViewAutoresizingFlexibleLeftMargin
// | UIViewAutoresizingFlexibleRightMargin
// | UIViewAutoresizingFlexibleTopMargin
| UIViewAutoresizingFlexibleWidth;
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleLabel.font = [UIFont fontWithName:@"Helvetica" size:13];
// titleLabel.minimumFontSize = 12;
titleLabel.minimumScaleFactor = 0.9;
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.backgroundColor = [UIColor clearColor];
// titleLabel.lineBreakMode = UILineBreakModeMiddleTruncation;
// TODO add a setting to do this
titleLabel.shadowOffset = CGSizeMake(0, 1);
titleLabel.shadowColor = [UIColor whiteColor];
titleLabel.text = NSLocalizedString(@"New Tab", @"New Tab");
[self addSubview:titleLabel];
// progess
// progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(29, 27, self.bounds.size.width - 60, 10)];
// [progressView setProgressViewStyle:UIProgressViewStyleBar];
// progressView.progress = 0.0;
// progressView.transform = CGAffineTransformMakeScale(1, 0.75);
// progressView.alpha = 0.5;
// progressView.autoresizingMask = UIViewAutoresizingFlexibleHeight
// // |UIViewAutoresizingFlexibleBottomMargin
// // | UIViewAutoresizingFlexibleLeftMargin
// // | UIViewAutoresizingFlexibleRightMargin
// // | UIViewAutoresizingFlexibleTopMargin
// | UIViewAutoresizingFlexibleWidth;
// progressView.contentMode = UIViewContentModeRedraw;
// [self addSubview: progressView];
// activity
indicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(self.bounds.size.width - 40, 8, 21, 21)];
indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[indicatorView startAnimating];
indicatorView.autoresizingMask = UIViewAutoresizingFlexibleHeight
// |UIViewAutoresizingFlexibleBottomMargin
| UIViewAutoresizingFlexibleLeftMargin;
// | UIViewAutoresizingFlexibleRightMargin
// | UIViewAutoresizingFlexibleTopMargin
// | UIViewAutoresizingFlexibleWidth;
indicatorView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
[self addSubview:indicatorView];
// [progressView release];
}
- (id)initWithFrame:(CGRect)frame
@@ -273,11 +244,6 @@
closeButton.accessibilityValue = title;
}
//-(void)setPercentage:(float)newPercentage {
// percentage = newPercentage;
// progressView.progress = newPercentage;
//}
-(void)setLoading:(BOOL)newLoading {
loading = newLoading;
if (newLoading) {

View File

@@ -8,6 +8,23 @@
#import <UIKit/UIKit.h>
@interface SWBViewController : UIViewController
#import "SWBTabBarView.h"
#import "SWBWebViewContainer.h"
#import "SWBPageManager.h"
@interface SWBViewController : UIViewController <SWBTabBarDelegate, SWBWebViewContainerDelegate> {
NSInteger lastTag;
NSInteger currentTabTag;
}
@property (nonatomic, strong) SWBTabBarView *tabBar;
@property (nonatomic, strong) SWBWebViewContainer *webViewContainer;
@property (nonatomic, retain) UIToolbar *toolBar;
@property (nonatomic, retain) UIActionSheet *actionSheet;
@property (nonatomic, retain) SWBPageManager *pageManager;
-(void)openLinkInNewTab:(NSString *)urlString;
-(void)savePageIndex;
-(void)saveData;
@end

View File

@@ -8,16 +8,33 @@
#import "SWBViewController.h"
#define kNewTabAddress @"shadowweb:newtab"
#define kAboutBlank @"shadowweb:blank"
@interface SWBViewController ()
@end
@implementation SWBViewController
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
currentTabTag = 0;
CGRect bounds = self.view.bounds;
self.tabBar = [[SWBTabBarView alloc] initWithFrame:CGRectMake(0, bounds.size.height - kTabBarHeight, bounds.size.width, kTabBarHeight)];
[self.view addSubview:self.tabBar];
self.webViewContainer = [[SWBWebViewContainer alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height - kTabBarHeight)];
_webViewContainer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:_webViewContainer];
_webViewContainer.delegate = self;
self.tabBar.delegate = self;
self.webViewContainer.delegate = self;
[self initPageManager];
[self initPagesAndTabs];
}
- (void)didReceiveMemoryWarning
@@ -26,4 +43,245 @@
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#pragma mark - webview
-(void)openURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url || [urlString rangeOfString:@":"].length == 0) {
urlString = [@"http://" stringByAppendingString:urlString];
url = [NSURL URLWithString:urlString];
}
if (url) {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
if (request) {
[_webViewContainer.currentSWBWebView loadRequest:request];
}
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"incorrect URL" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
}
-(SWBWebView *)currentWebView {
return [_webViewContainer currentSWBWebView];
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
BOOL result = YES;
#ifdef DEBUG
// NSLog(@"shouldStartLoadWithRequest tag:%d navtype:%d %@", webView.tag, navigationType, [request URL]);
#endif
// NSString *scheme = [[request URL] scheme];
if ([[[request URL] absoluteString] caseInsensitiveCompare:kNewTabAddress] == NSOrderedSame)
{
// [self openLinkInNewTab:[(SWBWebView *)webView lastClickedLink]];
}
else
{
if (navigationType == UIWebViewNavigationTypeLinkClicked ||
navigationType == UIWebViewNavigationTypeBackForward) {
SWBPage *page = [_pageManager pageByTag:webView.tag];
NSString *url = [[request URL] absoluteString];
page.url = url;
}
}
return result;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
if ([[[[webView request] URL] absoluteString] caseInsensitiveCompare: [(SWBWebView *)webView aqLocationHref]] == NSOrderedSame) {
NSString *url = [[[webView request] URL] absoluteString];
NSString *title = [((SWBWebView *)webView) pageTitle];
SWBPage *page = [_pageManager pageByTag:webView.tag];
page.url = url;
page.title = title;
}
}
-(void)webViewDidStartLoad:(UIWebView *)webView {
}
#pragma mark - TabBar
-(void)resetTabBarButtonsStatus {
// SWBWebView *currentWebView = [self currentWebView];
// backButton.enabled = currentWebView.canGoBack;
// forwardButton.enabled = currentWebView.canGoForward;
// stopButton.enabled = currentWebView.loading;
// @try {
// NSString *urlString = [[self currentWebView] aqLocationHref];
// NSURL *url = [NSURL URLWithString:urlString];
// if (AQ_is_nonlocal_http([url scheme])) {
// actionButton.enabled = YES;
// // refreshButton.enabled = YES;
// } else {
// actionButton.enabled = NO;
// // refreshButton.enabled = NO;
// }
// }
// @catch (NSException *exception) {
// }
// @finally {
// }
}
-(void)tabBarViewNewTabButtonDidClick {
[self openLinkInNewTab:kNewTabAddress];
}
-(void)tabBarViewTabDidClose:(SWBTab *)tab {
NSString *title = [[_webViewContainer webViewByTag:tab.tag] pageTitle];
NSString *urlString =[[_pageManager pageByTag:tab.tag] url];
// if (urlString) {
// NSURL *url = [[NSURL alloc] initWithString:urlString];
// if (AQ_is_nonlocal_http([url scheme])) {
// [visitRecordManager closeAURL:urlString withTitle:title];
// }
// [url release];
// }
[_pageManager removePage:tab.tag];
[_webViewContainer closeWebView:tab.tag];
if (_tabBar.currentTab) {
[_webViewContainer switchToWebView:_tabBar.currentTab.tag];
}
if ([[_pageManager pages] count] == 0) {
[self tabBarViewNewTabButtonDidClick];
}
}
-(void)tabBarViewTabDidMove:(SWBTab *)tab toIndex:(NSInteger)index {
// [pageManager reorderPage:tabBar.tabs];
//
}
-(void)tabBarViewTabDidSelect:(SWBTab *)tab {
[_webViewContainer switchToWebView:tab.tag];
}
#pragma mark - page manager
-(void)initPageManager {
lastTag = 0;
self.pageManager = [[SWBPageManager alloc] init];
[_pageManager load];
}
-(NSInteger)genTag {
return lastTag ++;
}
-(void)initPagesAndTabs {
[_pageManager initMappingAndTabsByPages];
NSArray *pages = _pageManager.pages;
// NSInteger currentTabTag = 0;
NSUInteger count = [pages count];
for (int i = 0; i < count; i++) {
if ([[[pages objectAtIndex:i] selected] boolValue]) {
currentTabTag = i;
}
}
for (int i = 0; i < count; i++) {
[self addNewTab];
}
if ([pages count] == 0) {
[self tabBarViewNewTabButtonDidClick];
} else {
[_tabBar setCurrentTabWithTag:currentTabTag];
}
}
-(void)savePageIndex {
// save page index order
// NSArray *tabs = [tabBar tabs];
// for (int i = 0; i < [tabs count]; i++) {
// [[pageManager pageByTag:[[tabs objectAtIndex:i] tag]] setIndex:[NSNumber numberWithInt:i]];
// }
}
- (void)addNewEmptyTab {
NSInteger newTag = [self genTag];
[_webViewContainer newWebView:newTag];
}
- (void)addNewTab {
SWBTab *newTab = [_tabBar newTab];
[_webViewContainer newWebView:newTab.tag];
_tabBar.currentTab = newTab;
}
-(void)openLinkInNewTab:(NSString *)urlString {
SWBTab *newTab = [_tabBar newTab];
SWBPage *page = [_pageManager addPageWithTag:newTab.tag];
page.url = urlString;
page.title = @"";
[_webViewContainer newWebView:newTab.tag];
_tabBar.currentTab = newTab;
}
-(void)saveData {
[_pageManager save];
}
#pragma mark - WebViewContainer
-(void)syncPageManagerSelectionStatusWithSelectedTag:(NSInteger)tag {
NSNumber *yes = [NSNumber numberWithBool:YES];
NSNumber *no = [NSNumber numberWithBool:NO];
for (SWBPage *page in _pageManager.pages) {
page.selected = no;
}
[_pageManager pageByTag:tag].selected = yes;
}
-(void)webViewContainerWebViewDidCreateNew:(SWBWebView *)webView {
SWBPage *page = [_pageManager pageByTag:webView.tag];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:page.url]];
NSRange range = [page.url rangeOfString:@"file:"];
if (range.length > 0 && range.location == 0) {
if ([page.url rangeOfString:@"home.min.htm"].length > 0) {
request = [NSURLRequest requestWithURL:[NSURL URLWithString:kAboutBlank]];
}
}
[webView loadRequest:request];
[self resetTabBarButtonsStatus];
[self syncPageManagerSelectionStatusWithSelectedTag:webView.tag];
}
-(void)webViewContainerWebViewDidSwitchToWebView:(SWBWebView *)webView {
[self resetTabBarButtonsStatus];
[self syncPageManagerSelectionStatusWithSelectedTag:webView.tag];
}
-(void)webViewContainerWebViewNeedToReload:(SWBWebView *)webView tag:(NSInteger)tag {
SWBPage *page = [_pageManager pageByTag:tag];
NSURL *url = [NSURL URLWithString:page.url];
if (url!=nil) {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
[self resetTabBarButtonsStatus];
}
}
@end

26
ShadowWeb/SWBWebView.h Normal file
View File

@@ -0,0 +1,26 @@
//
// SWBWebView.h
// AquaWeb
//
// Created by clowwindy on 11-6-16.
// Copyright 2011年 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SWBWebView : UIWebView {
}
- (NSString *)pageTitle;
- (NSString *)aqLocationHref;
- (CGSize)windowSize;
- (CGPoint)scrollOffset;
- (NSString *)lastClickedLink;
- (NSString *)lastClickedLinkText;
- (NSString *)lastImageSrc;
- (void)openLastClickedLink;
- (NSString *)selection;
@end

115
ShadowWeb/SWBWebView.m Normal file
View File

@@ -0,0 +1,115 @@
//
// SWBWebView.m
// AquaWeb
//
// Created by clowwindy on 11-6-16.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SWBWebView.h"
#import <QuartzCore/QuartzCore.h>
@implementation SWBWebView
//+(Class)layerClass {
// return [CATiledLayer class];
//}
//-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//
//}
//
//- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// UITouch *theTouch = [touches anyObject];
// if ([theTouch tapCount] == 2) {
// [self becomeFirstResponder];
// UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Change Color" action:@selector(changeColor:)];
// UIMenuController *menuCont = [UIMenuController sharedMenuController];
// [menuCont setTargetRect:self.frame inView:self.superview];
// menuCont.arrowDirection = UIMenuControllerArrowLeft;
// menuCont.menuItems = [NSArray arrayWithObject:menuItem];
// [menuCont setMenuVisible:YES animated:YES];
// }
// [super touchesEnded:touches withEvent:event];
//}
//- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {}
- (BOOL)canBecomeFirstResponder { return YES; }
- (void)changeColor:(id)sender {
// if ([self.viewColor isEqual:[UIColor blackColor]]) {
// self.viewColor = [UIColor redColor];
// } else {
// self.viewColor = [UIColor blackColor];
// }
[self setNeedsDisplay];
}
- (CGSize)windowSize
{
CGSize size;
size.width = [[self stringByEvaluatingJavaScriptFromString:@"window.innerWidth"] integerValue];
size.height = [[self stringByEvaluatingJavaScriptFromString:@"window.innerHeight"] integerValue];
return size;
}
- (CGPoint)scrollOffset
{
CGPoint pt;
pt.x = [[self stringByEvaluatingJavaScriptFromString:@"window.pageXOffset"] integerValue];
pt.y = [[self stringByEvaluatingJavaScriptFromString:@"window.pageYOffset"] integerValue];
return pt;
}
-(NSString *)lastClickedLink {
NSString *urlString = [self stringByEvaluatingJavaScriptFromString:@"AquaWebGetLastLink()"];
if ([NSURL URLWithString:urlString] == nil) {
return [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
} else {
return urlString;
}
}
-(NSString *)lastClickedLinkText {
NSString *urlString = [self stringByEvaluatingJavaScriptFromString:@"AquaWebGetLastLinkText()"];
return urlString;
}
-(NSString *)lastImageSrc {
NSString *urlString = [self stringByEvaluatingJavaScriptFromString:@"AquaWebGetLastImageSrc()"];
if ([NSURL URLWithString:urlString] == nil) {
return [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
} else {
return urlString;
}
}
-(void)openLastClickedLink {
[self stringByEvaluatingJavaScriptFromString:@"AquaWebOpenLastLink()"];
}
-(NSString *)aqLocationHref {
NSString *urlString = [self stringByEvaluatingJavaScriptFromString:@"window.location.href"];
if ([NSURL URLWithString:urlString] == nil) {
return [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
} else {
return urlString;
}
}
-(NSString *)pageTitle {
return [self stringByEvaluatingJavaScriptFromString:@"document.title"];
}
-(NSString *)selection {
NSString *selection = [self stringByEvaluatingJavaScriptFromString:@"if(window.getSelection()){window.getSelection().toString()}else{""}"];
return selection;
}
//- (void)dealloc {
//
// [super dealloc];
//}
@end

View File

@@ -0,0 +1,52 @@
//
// SWBWebViewContainer.h
// AquaWeb
//
// Created by clowwindy on 11-6-16.
// Copyright 2011年 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SWBWebView.h"
#define kMaxCachedWebViews 10
#define kMinCachedWebViews 2
@protocol SWBWebViewContainerDelegate <UIWebViewDelegate>
@required
-(void)webViewContainerWebViewDidCreateNew:(SWBWebView *)webView;
-(void)webViewContainerWebViewDidSwitchToWebView:(SWBWebView *)webView;
-(void)webViewContainerWebViewNeedToReload:(SWBWebView *)webView tag:(NSInteger)tag;
@end
@interface SWBWebViewContainer : UIView <UIWebViewDelegate> {
// 最旧的在0最新的在末尾
NSMutableArray *cachedWebViews;
SWBWebView *currentWebView;
NSString *s;
}
- (void)newWebView:(NSInteger)tag;
- (void)switchToWebView:(NSInteger)tag;
- (void)closeWebView:(NSInteger)tag;
- (SWBWebView *)webViewByTag:(NSInteger)tag;
- (NSInteger)currentWebView;
- (SWBWebView *)currentSWBWebView;
// 彻底释放,适合内存严重不足
- (void)releaseBackgroundWebViews;
// 仅从superview移除可以节省部分内存
- (void)removeBackgroundWebViewsFromSuperView;
- (NSString *)titleForWebView:(SWBWebView *)webView;
//- (void)progressEstimateChanged:(NSNotification*)theNotification;
@property (nonatomic, weak) id<SWBWebViewContainerDelegate> delegate;
@end

View File

@@ -0,0 +1,276 @@
//
// SWBWebViewContainer.m
// AquaWeb
//
// Created by clowwindy on 11-6-16.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "SWBWebViewContainer.h"
#import "SWBAppDelegate.h"
//#import "WebView.h"
//#import "UIWebDocumentView.h"
@implementation SWBWebViewContainer
@synthesize delegate;
-(void)loadDefaults {
cachedWebViews = [[NSMutableArray alloc] init];
s = [[NSString alloc] initWithFormat:@"_%@:", @"setDrawInWebThread"];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self loadDefaults];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// Initialization code
[self loadDefaults];
}
return self;
}
- (void)setNetworkIndicatorStatus {
BOOL loading = NO;
for (SWBWebView *webView in cachedWebViews) {
loading |= webView.loading;
}
[appNetworkActivityIndicatorManager setSourceActivityStatusIsBusy:self busy:loading];
// [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:loading];
}
- (void)moveWebViewToCacheQueueEnd:(SWBWebView *)webView {
// TODO
if ([cachedWebViews containsObject:webView]) {
[cachedWebViews removeObject:webView];
}
[cachedWebViews addObject:webView];
}
//- (void)progressEstimateChanged:(NSNotification*)theNotification {
// // You can get the progress as a float with
// // [[theNotification object] estimatedProgress], and then you
// // can set that to a UIProgressView if you'd like.
// // theProgressView is just an example of what you could do.
//
//// [theProgressView setProgress:[[theNotification object] estimatedProgress]];
//
// NSLog(@"%@",[[theNotification object] estimatedProgress]);
//
// if ((int)[[theNotification object] estimatedProgress] == 1) {
//// theProgressView.hidden = TRUE;
// // Hide the progress view. This is optional, but depending on where
// // you put it, this may be a good idea.
// // If you wanted to do this, you'd
// // have to set theProgressView to visible in your
// // webViewDidStartLoad delegate method,
// // see Apple's UIWebView documentation.
// }
//}
- (void)initAWebView:(SWBWebView *)webView {
// webView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
// cause crash on double-tap
@try {
SEL ss = NSSelectorFromString(s);
if ([webView respondsToSelector:ss]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIWebView instanceMethodSignatureForSelector:ss]];
BOOL setting = YES;
[invocation setSelector:ss];
[invocation setTarget:webView];
[invocation setArgument:&setting atIndex:2];
[invocation invoke];
// [webView performSelector:ss withObject:YES];
}
}
@catch (NSException *exception) {
NSLog(@"%@", exception);
}
@finally {
}
webView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight
| UIViewAutoresizingFlexibleWidth;
webView.multipleTouchEnabled = YES;
webView.scalesPageToFit = YES;
webView.delegate = self;
// UIWebDocumentView *documentView = [webView _documentView];
// WebView *coreWebView = [documentView webView];
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(progressEstimateChanged:) name:@"WebViewProgressEstimateChangedNotification" object:coreWebView];
// [coreWebView estimatedProgress
}
- (void)removeAWebView:(SWBWebView *)webView {
webView.delegate = nil;
// // fix memory leaks
// [webView loadHTMLString:@"" baseURL:nil];
[cachedWebViews removeObject:webView];
if (webView.superview) {
[webView removeFromSuperview];
}
}
- (SWBWebView *)getANewWebView {
NSInteger count = [cachedWebViews count];
if (count >= kMaxCachedWebViews) {
[self removeAWebView:[cachedWebViews objectAtIndex:0]];
}
SWBWebView *webView = [[SWBWebView alloc] init];
[self initAWebView:webView];
[cachedWebViews addObject:webView];
return webView;
}
- (void)switchToWebViewWithWebView:(SWBWebView *)webView {
[self moveWebViewToCacheQueueEnd:webView];
// if (currentWebView) {
// [currentWebView removeFromSuperview];
// }
if (currentWebView && currentWebView != webView) {
//
currentWebView.autoresizingMask = UIViewAutoresizingNone;
// currentWebView.hidden = YES;
@try {
((UIScrollView *)[[currentWebView subviews] objectAtIndex:0]).scrollsToTop = NO;
}
@catch (NSException *exception) {
}
@finally {
}
}
if (webView.superview) {
[self bringSubviewToFront:webView];
} else {
// webView.frame = CGRectZero;
[self addSubview:webView];
}
// webView.hidden = NO;
@try {
((UIScrollView *)[[webView subviews] objectAtIndex:0]).scrollsToTop = YES;
}
@catch (NSException *exception) {
}
@finally {
}
currentWebView = webView;
//
webView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight
| UIViewAutoresizingFlexibleWidth;
}
- (void)newWebView:(NSInteger)tag {
SWBWebView *webView = [self getANewWebView];
webView.tag = tag;
[self switchToWebViewWithWebView:webView];
[delegate webViewContainerWebViewDidCreateNew:webView];
}
- (void)switchToWebView:(NSInteger)tag {
SWBWebView *webView = [self webViewByTag:tag];
if (currentWebView && currentWebView == webView) {
// do not compare tags, because currentWebView may be released
return;
}
[self switchToWebViewWithWebView:webView];
[delegate webViewContainerWebViewDidSwitchToWebView:webView];
}
- (void)closeWebView:(NSInteger)tag {
if (tag == currentWebView.tag) {
currentWebView = nil;
}
[self removeAWebView:[self webViewByTag:tag]];
}
- (SWBWebView *)webViewByTag:(NSInteger)tag {
for (SWBWebView *webView in cachedWebViews) {
if (webView.tag == tag) {
return webView;
}
}
SWBWebView *webView = [self getANewWebView];
webView.tag = tag;
[delegate webViewContainerWebViewNeedToReload:webView tag:tag];
return webView;
}
- (NSInteger)currentWebView {
return currentWebView.tag;
}
- (SWBWebView *)currentSWBWebView {
return currentWebView;
}
- (void)releaseBackgroundWebViews {
NSInteger count = [cachedWebViews count];
for (int i = 0; i < count - kMinCachedWebViews; i ++) {
[(UIWebView *)[cachedWebViews objectAtIndex:0] removeFromSuperview];
[cachedWebViews removeObjectAtIndex:0];
}
}
- (void)removeBackgroundWebViewsFromSuperView {
NSInteger count = [cachedWebViews count];
for (int i = 0; i < count - kMinCachedWebViews; i ++) {
[(UIWebView *)[cachedWebViews objectAtIndex:i] removeFromSuperview];
}
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[delegate webView:webView didFailLoadWithError:error];
[self setNetworkIndicatorStatus];
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (delegate) {
[delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}
return YES;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
[delegate webViewDidFinishLoad:webView];
[self setNetworkIndicatorStatus];
}
-(void)webViewDidStartLoad:(UIWebView *)webView {
[delegate webViewDidStartLoad:webView];
[self setNetworkIndicatorStatus];
}
-(NSString *)titleForWebView:(SWBWebView *)webView {
NSString *theTitle = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
return theTitle;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end