├── .gitignore ├── Cakefile ├── JavaUniverse-iOS ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── PJUAFDataSource.h ├── PJUAFDataSource.m ├── PJUWindowManager.h ├── PJUWindowManager.m ├── PJUiOSGuiWrapper.h ├── PJUiOSGuiWrapper.m ├── UIView+PJUWindow.h ├── UIView+PJUWindow.m ├── ViewController.h ├── ViewController.m └── main.m ├── JavaUniverse ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── android │ └── java │ │ └── com │ │ └── github │ │ └── piasy │ │ └── java_universe │ │ ├── WindowManager.java │ │ └── android │ │ ├── AndroidGuiWrapper.java │ │ └── RetrofitDataSource.java │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── github │ └── piasy │ └── java_universe │ ├── DataSource.java │ ├── GuiWrapper.java │ ├── TextUtils.java │ ├── Window.java │ └── WindowManagerCore.java ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── github │ │ └── piasy │ │ └── java_universe │ │ └── example │ │ └── MainActivity.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ └── activity_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── setup_xcode_project.sh /.gitignore: -------------------------------------------------------------------------------- 1 | **.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | 10 | *.xcodeproj/ 11 | *.xcworkspace/ 12 | Pods/ 13 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | # Change this to set a different Project file name 2 | project.name = "JavaUniverse-iOS" 3 | 4 | # Replace this with your class prefix for Objective-C files. 5 | project.organization = "com.github.piasy" 6 | project.class_prefix = "PJU" 7 | 8 | # By default Xcake defaults to creating the standard Debug and Release 9 | # configurations, uncomment these lines to add your own. 10 | # 11 | #debug_configuration :Staging 12 | #debug_configuration :Debug 13 | #release_configuration :Release 14 | 15 | # Change these to the platform you wish to support (ios, osx) and the 16 | # version of that platform (8.0, 9.0, 10.10, 10.11) 17 | # 18 | application_for :ios, 11.1 do |target| 19 | 20 | #Update these with the details of your app 21 | target.name = "JavaUniverse-iOS" 22 | target.all_configurations.each { |c| c.product_bundle_identifier = "com.github.piasy.JavaUniverse-iOS"} 23 | 24 | # Uncomment to target iPhone devices only 25 | # 26 | # File patterns can be seen here https://guides.cocoapods.org/syntax/podspec.html#group_file_patterns 27 | # 28 | target.all_configurations.each { |c| c.supported_devices = :iphone_only} 29 | 30 | # Uncomment this to include additional files 31 | # 32 | target.include_files << "./JavaUniverse/src/main/java/**/*.java" 33 | 34 | # Uncomment this to exclude additional files 35 | # 36 | # File patterns can be seen here https://guides.cocoapods.org/syntax/podspec.html#group_file_patterns 37 | # 38 | #target.exclude_files << "ExcludeToInclude/*.*" 39 | 40 | # Uncomment to set your own build settings 41 | target.all_configurations.each do |c| 42 | c.settings["INFOPLIST_FILE"] = "JavaUniverse-iOS/Info.plist" 43 | c.settings["J2OBJC_HOME"] = "/usr/local/j2objc" 44 | c.settings["OTHER_LDFLAGS"] = "$(inherited) -ljre_emul -liconv -lz" 45 | c.settings["FRAMEWORK_SEARCH_PATHS"] = "$(inherited) ${J2OBJC_HOME}/frameworks" 46 | c.settings["LIBRARY_SEARCH_PATHS"] = "$(inherited) ${J2OBJC_HOME}/lib" 47 | c.settings["USER_HEADER_SEARCH_PATHS"] = "$(inherited) ${J2OBJC_HOME}/include" 48 | end 49 | 50 | target.build_rule "Compile Java to ObjC", "sourcecode.java", ["${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.h", "${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.m"], [], <<-SCRIPT 51 | if [ ! -f "${J2OBJC_HOME}/j2objc" ]; then \ 52 | echo "J2OBJC_HOME not correctly defined in Settings.xcconfig, currently set to '${J2OBJC_HOME}'"; \ 53 | exit 1; fi; 54 | "${J2OBJC_HOME}/j2objc" -d ${DERIVED_FILES_DIR} \ 55 | -sourcepath "${PROJECT_DIR}/JavaUniverse/src/main/java" \ 56 | --no-package-directories -use-arc \ 57 | --prefix com.github.piasy.java_universe=PJU \ 58 | -g ${INPUT_FILE_PATH}; 59 | SCRIPT 60 | # 61 | #target.all_configurations.each { |c| c.settings["ENABLE_BITCODE"] = "NO"} 62 | #target.all_configurations.each { |c| c.settings["GCC_PREFIX_HEADER"] = "APP-Prefix-Header.pch"} 63 | #target.all_configurations.each { |c| c.settings["SWIFT_OBJC_BRIDGING_HEADER"] = "APP-Bridging-Header.h"} 64 | 65 | # Uncomment to define your own preprocessor macros 66 | # 67 | #target.all_configurations.each { |c| c.preprocessor_definitions["API_ENDPOINT"] = "https://example.org".to_obj_c} 68 | 69 | # Comment to remove Unit Tests for your app 70 | # 71 | # unit_tests_for target 72 | 73 | # Uncomment to create a Watch App for your application. 74 | # 75 | #watch_app_for target, 2.0 76 | end 77 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /JavaUniverse-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUAFDataSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFNetworkingDataSource.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "DataSource.h" 12 | 13 | @interface PJUAFDataSource : NSObject 14 | - (instancetype)init; 15 | @end 16 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUAFDataSource.m: -------------------------------------------------------------------------------- 1 | // 2 | // AFNetworkingDataSource.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "java/util/ArrayList.h" 12 | 13 | #import "Window.h" 14 | 15 | #import "PJUAFDataSource.h" 16 | 17 | @implementation PJUAFDataSource { 18 | NSURLSessionConfiguration* _conf; 19 | AFURLSessionManager* _manager; 20 | } 21 | 22 | - (instancetype)init { 23 | self = [super init]; 24 | if (self) { 25 | _conf = [NSURLSessionConfiguration defaultSessionConfiguration]; 26 | _manager = 27 | [[AFURLSessionManager alloc] initWithSessionConfiguration:_conf]; 28 | } 29 | return self; 30 | } 31 | 32 | - (void)getWindowsWithPage:(jint)page 33 | num:(jint)num 34 | callback:(id)callback { 35 | NSURL* url = 36 | [NSURL URLWithString:@"https://imgs.babits.top/windows_4.json"]; 37 | NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url]; 38 | NSURLSessionDataTask* task = [_manager 39 | dataTaskWithRequest:request 40 | completionHandler:^(NSURLResponse* _Nonnull response, 41 | id _Nullable responseObject, 42 | NSError* _Nullable error) { 43 | JavaUtilArrayList* list = [[JavaUtilArrayList alloc] init]; 44 | for (NSDictionary* obj in responseObject) { 45 | PJUWindow* window = [[PJUWindow alloc] 46 | initWithWidth:[obj[@"width"] integerValue] 47 | height:[obj[@"height"] integerValue] 48 | top:[obj[@"top"] integerValue] 49 | left:[obj[@"left"] integerValue] 50 | zIndex:[obj[@"z_index"] integerValue] 51 | uid:obj[@"uid"]]; 52 | [list addWithId:window]; 53 | } 54 | [callback onSuccess:list]; 55 | }]; 56 | [task resume]; 57 | } 58 | 59 | @end 60 | 61 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUWindowManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // PJUWindowManager.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "WindowManagerCore.h" 13 | 14 | @interface PJUWindowManager : PJUWindowManagerCore 15 | - (instancetype)initWithContainer:(UIView*)container 16 | andCallback:(id)callback; 17 | @end 18 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUWindowManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // PJUWindowManager.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import "PJUWindowManager.h" 10 | #import "PJUAFDataSource.h" 11 | #import "PJUiOSGuiWrapper.h" 12 | 13 | @implementation PJUWindowManager 14 | - (instancetype)initWithContainer:(UIView*)container 15 | andCallback:(id)callback { 16 | self = [super initWithPJUDataSource:[[PJUAFDataSource alloc] init] 17 | withPJUGuiWrapper:[[PJUiOSGuiWrapper alloc] 18 | initWithContainer:container] 19 | withPJUWindowManagerCore_Callback:callback]; 20 | return self; 21 | } 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUiOSGuiWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // PJUiOSGuiWrapper.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "GuiWrapper.h" 13 | 14 | @interface PJUiOSGuiWrapper : NSObject 15 | - (instancetype)initWithContainer:(UIView*)container; 16 | @end 17 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/PJUiOSGuiWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // PJUiOSGuiWrapper.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import "Window.h" 10 | 11 | #import "PJUiOSGuiWrapper.h" 12 | #import "UIView+PJUWindow.h" 13 | 14 | static const int32_t kMatchParentSize = 10000; 15 | 16 | CGFloat getSize(CGFloat full, int32_t size) { 17 | return full * size / kMatchParentSize; 18 | } 19 | 20 | @implementation PJUiOSGuiWrapper { 21 | NSArray* _colors; 22 | UIView* _container; 23 | CGFloat _containerWidth; 24 | CGFloat _containerHeight; 25 | } 26 | 27 | - (instancetype)initWithContainer:(UIView*)container { 28 | self = [super init]; 29 | if (self) { 30 | _colors = 31 | [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], 32 | [UIColor blueColor], nil]; 33 | _container = container; 34 | _containerWidth = _container.bounds.size.width; 35 | _containerHeight = _container.bounds.size.height; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)clearView { 41 | [[_container subviews] 42 | makeObjectsPerformSelector:@selector(removeFromSuperview)]; 43 | } 44 | 45 | - (void)createViewWithWindow:(PJUWindow*)window { 46 | UILabel* label = [[UILabel alloc] 47 | initWithFrame:CGRectMake(getSize(_containerWidth, window.left), 48 | getSize(_containerHeight, window.top), 49 | getSize(_containerWidth, window.width), 50 | getSize(_containerHeight, window.height))]; 51 | label.text = window.uid; 52 | label.textAlignment = NSTextAlignmentCenter; 53 | label.backgroundColor = _colors[_container.subviews.count % _colors.count]; 54 | label.pjuWindow = window; 55 | 56 | [_container addSubview:label]; 57 | } 58 | 59 | - (void)swapViewWithWindow:(PJUWindow*)alice andWindow:(PJUWindow*)bob { 60 | UIView* aliceView = nil; 61 | UIView* bobView = nil; 62 | for (UIView* view in _container.subviews) { 63 | if ([view.pjuWindow.uid isEqualToString:alice.uid]) { 64 | aliceView = view; 65 | } else if ([view.pjuWindow.uid isEqualToString:bob.uid]) { 66 | bobView = view; 67 | } 68 | } 69 | if (aliceView == nil || bobView == nil || aliceView == bobView) { 70 | return; 71 | } 72 | [aliceView.pjuWindow swapWithWindow:bobView.pjuWindow]; 73 | 74 | [self applyWindowSize]; 75 | } 76 | 77 | - (void)applyWindowSize { 78 | NSArray* children = [_container.subviews 79 | sortedArrayUsingComparator:^NSComparisonResult(UIView* v1, UIView* v2) { 80 | int32_t z1 = v1.pjuWindow.z_index; 81 | int32_t z2 = v2.pjuWindow.z_index; 82 | return z1 < z2 ? NSOrderedAscending : NSOrderedDescending; 83 | }]; 84 | for (UIView* child in children) { 85 | PJUWindow* window = child.pjuWindow; 86 | child.frame = CGRectMake(getSize(_containerWidth, window.left), 87 | getSize(_containerHeight, window.top), 88 | getSize(_containerWidth, window.width), 89 | getSize(_containerHeight, window.height)); 90 | [_container bringSubviewToFront:child]; 91 | } 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/UIView+PJUWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Tag.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 10/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "Window.h" 13 | 14 | @interface UIView (PJUWindow) 15 | @property PJUWindow* pjuWindow; 16 | @end 17 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/UIView+PJUWindow.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // UIView+Tag.m 5 | // JavaUniverse-iOS 6 | // 7 | // Created by Piasy on 10/11/2017. 8 | // Copyright © 2017 Piasy. All rights reserved. 9 | // 10 | 11 | #import 12 | 13 | #import "UIView+PJUWindow.h" 14 | 15 | static const void* kWindowKey = @"kWindowKey"; 16 | 17 | @implementation UIView (PJUWindow) 18 | - (PJUWindow*)pjuWindow { 19 | return objc_getAssociatedObject(self, kWindowKey); 20 | } 21 | 22 | - (void)setPjuWindow:(PJUWindow*)pjuWindow { 23 | objc_setAssociatedObject(self, kWindowKey, pjuWindow, 24 | OBJC_ASSOCIATION_ASSIGN); 25 | } 26 | @end 27 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "WindowManagerCore.h" 12 | 13 | @interface ViewController : UIViewController 14 | // MARK: Properties 15 | @property(weak, nonatomic) IBOutlet UIView* container; 16 | 17 | // MARK: Actions 18 | - (IBAction)onShuffle:(UIButton*)sender; 19 | @end 20 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import "Window.h" 10 | 11 | #import "ViewController.h" 12 | #import "PJUWindowManager.h" 13 | 14 | @interface ViewController () 15 | 16 | @end 17 | 18 | @implementation ViewController { 19 | PJUWindowManager* _windowManager; 20 | NSMutableArray* _users; 21 | int _currentFcIndex; 22 | } 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | _windowManager = [[PJUWindowManager alloc] initWithContainer:self.container 28 | andCallback:self]; 29 | _users = [[NSMutableArray alloc] init]; 30 | _currentFcIndex = 0; 31 | 32 | [_windowManager loadWindows]; 33 | } 34 | 35 | - (void)didReceiveMemoryWarning { 36 | [super didReceiveMemoryWarning]; 37 | // Dispose of any resources that can be recreated. 38 | } 39 | 40 | - (void)onWindowAdded:(PJUWindow*)window { 41 | [_users addObject:[window getUid]]; 42 | } 43 | 44 | - (void)onError:(jint)error { 45 | NSLog(@"onError %d", error); 46 | } 47 | 48 | - (IBAction)onShuffle:(UIButton*)sender { 49 | _currentFcIndex = (_currentFcIndex + 1) % _users.count; 50 | NSLog(@"toggleFc %@", _users[_currentFcIndex]); 51 | [_windowManager toggleFullscreenWithNSString:_users[_currentFcIndex]]; 52 | } 53 | @end 54 | -------------------------------------------------------------------------------- /JavaUniverse-iOS/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JavaUniverse-iOS 4 | // 5 | // Created by Piasy on 09/11/2017. 6 | // Copyright © 2017 Piasy. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /JavaUniverse/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /JavaUniverse/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | apply plugin: 'com.android.library' 26 | 27 | android { 28 | compileSdkVersion rootProject.ext.androidCompileSdkVersion 29 | 30 | defaultConfig { 31 | minSdkVersion rootProject.ext.minSdkVersion 32 | targetSdkVersion rootProject.ext.targetSdkVersion 33 | versionCode rootProject.ext.releaseVersionCode 34 | versionName rootProject.ext.releaseVersionName 35 | 36 | sourceSets.main.java.srcDirs = ['src/main/java', 'src/android/java'] 37 | } 38 | 39 | buildTypes { 40 | release { 41 | minifyEnabled false 42 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 43 | } 44 | } 45 | } 46 | 47 | dependencies { 48 | implementation 'com.squareup.retrofit2:retrofit:2.3.0' 49 | implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 50 | 51 | // https://mvnrepository.com/artifact/com.google.j2objc/j2objc-annotations 52 | compileOnly group: 'com.google.j2objc', name: 'j2objc-annotations', version: '1.3' 53 | } 54 | -------------------------------------------------------------------------------- /JavaUniverse/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /JavaUniverse/src/android/java/com/github/piasy/java_universe/WindowManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | import android.view.ViewGroup; 28 | import com.github.piasy.java_universe.android.AndroidGuiWrapper; 29 | import com.github.piasy.java_universe.android.RetrofitDataSource; 30 | 31 | /** 32 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 33 | */ 34 | 35 | public class WindowManager extends WindowManagerCore { 36 | 37 | public WindowManager(final ViewGroup container, final Callback callback) { 38 | super(new RetrofitDataSource(), new AndroidGuiWrapper(container), callback); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /JavaUniverse/src/android/java/com/github/piasy/java_universe/android/AndroidGuiWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe.android; 26 | 27 | import android.graphics.Color; 28 | import android.view.Gravity; 29 | import android.view.View; 30 | import android.view.ViewGroup; 31 | import android.widget.FrameLayout; 32 | import android.widget.TextView; 33 | import com.github.piasy.java_universe.GuiWrapper; 34 | import com.github.piasy.java_universe.TextUtils; 35 | import com.github.piasy.java_universe.Window; 36 | import java.util.Arrays; 37 | import java.util.Comparator; 38 | 39 | /** 40 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 41 | */ 42 | 43 | public class AndroidGuiWrapper implements GuiWrapper { 44 | private static final int[] COLORS = new int[] { 45 | Color.RED, Color.GREEN, Color.BLUE 46 | }; 47 | 48 | private final ViewGroup mContainer; 49 | 50 | private int mContainerWidth; 51 | private int mContainerHeight; 52 | 53 | public AndroidGuiWrapper(final ViewGroup container) { 54 | mContainer = container; 55 | } 56 | 57 | @Override 58 | public void createView(final Window window) { 59 | if (mContainerWidth == 0) { 60 | mContainerWidth = mContainer.getWidth(); 61 | mContainerHeight = mContainer.getHeight(); 62 | } 63 | 64 | TextView textView = new TextView(mContainer.getContext()); 65 | 66 | textView.setText(window.getUid()); 67 | textView.setGravity(Gravity.CENTER); 68 | textView.setBackgroundColor(COLORS[mContainer.getChildCount() % COLORS.length]); 69 | 70 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( 71 | getSize(mContainerWidth, window.getWidth()), 72 | getSize(mContainerHeight, window.getHeight())); 73 | params.leftMargin = getSize(mContainerWidth, window.getLeft()); 74 | params.topMargin = getSize(mContainerHeight, window.getTop()); 75 | mContainer.addView(textView, params); 76 | 77 | textView.setTag(window); 78 | } 79 | 80 | @Override 81 | public void swapView(final Window alice, final Window bob) { 82 | View aliceView = null; 83 | View bobView = null; 84 | final int size = mContainer.getChildCount(); 85 | for (int i = 0; i < size; i++) { 86 | if (mContainer.getChildAt(i).getTag() instanceof Window) { 87 | if (TextUtils.equals(alice.getUid(), 88 | ((Window) mContainer.getChildAt(i).getTag()).getUid())) { 89 | aliceView = mContainer.getChildAt(i); 90 | } else if (TextUtils.equals(bob.getUid(), 91 | ((Window) mContainer.getChildAt(i).getTag()).getUid())) { 92 | bobView = mContainer.getChildAt(i); 93 | } 94 | } 95 | } 96 | 97 | if (aliceView == null || bobView == null || aliceView == bobView) { 98 | return; 99 | } 100 | 101 | ((Window) aliceView.getTag()).swap((Window) bobView.getTag()); 102 | 103 | applyWindowSize(); 104 | } 105 | 106 | @Override 107 | public void clearView() { 108 | mContainer.removeAllViews(); 109 | } 110 | 111 | private void applyWindowSize() { 112 | int n = mContainer.getChildCount(); 113 | View[] children = new View[n]; 114 | for (int i = 0; i < n; i++) { 115 | children[i] = mContainer.getChildAt(i); 116 | } 117 | Arrays.sort(children, new Comparator() { 118 | @Override 119 | public int compare(final View v1, final View v2) { 120 | Window w1 = (Window) v1.getTag(); 121 | Window w2 = (Window) v2.getTag(); 122 | return w1.getZ_index() - w2.getZ_index(); 123 | } 124 | }); 125 | 126 | for (View child : children) { 127 | Window window = (Window) child.getTag(); 128 | FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) child.getLayoutParams(); 129 | params.width = getSize(mContainerWidth, window.getWidth()); 130 | params.height = getSize(mContainerHeight, window.getHeight()); 131 | params.leftMargin = getSize(mContainerWidth, window.getLeft()); 132 | params.topMargin = getSize(mContainerHeight, window.getTop()); 133 | child.setLayoutParams(params); 134 | child.bringToFront(); 135 | } 136 | } 137 | 138 | private int getSize(int full, int size) { 139 | return full * size / Window.MATCH_PARENT; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /JavaUniverse/src/android/java/com/github/piasy/java_universe/android/RetrofitDataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe.android; 26 | 27 | import com.github.piasy.java_universe.DataSource; 28 | import com.github.piasy.java_universe.Window; 29 | import java.util.List; 30 | import retrofit2.Call; 31 | import retrofit2.Response; 32 | import retrofit2.Retrofit; 33 | import retrofit2.converter.gson.GsonConverterFactory; 34 | import retrofit2.http.GET; 35 | import retrofit2.http.Path; 36 | 37 | /** 38 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 39 | */ 40 | 41 | public class RetrofitDataSource implements DataSource { 42 | private final Api mApi; 43 | 44 | public RetrofitDataSource() { 45 | // callback in main thread by default 46 | mApi = new Retrofit.Builder() 47 | .baseUrl("https://imgs.babits.top/") 48 | .addConverterFactory(GsonConverterFactory.create()) 49 | .build() 50 | .create(Api.class); 51 | } 52 | 53 | @Override 54 | public void getWindows(final int page, final int num, final Callback> callback) { 55 | mApi.getWindows("windows_4.json") 56 | .enqueue(new retrofit2.Callback>() { 57 | @Override 58 | public void onResponse(final Call> call, 59 | final Response> response) { 60 | callback.onSuccess(response.body()); 61 | } 62 | 63 | @Override 64 | public void onFailure(final Call> call, final Throwable t) { 65 | callback.onFailure(DataSource.ERR_API_FAIL); 66 | } 67 | }); 68 | } 69 | 70 | interface Api { 71 | @GET("{path}") 72 | Call> getWindows(@Path("path") String path); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/java/com/github/piasy/java_universe/DataSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | import com.google.j2objc.annotations.ObjectiveCName; 28 | import java.util.List; 29 | 30 | /** 31 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 32 | */ 33 | 34 | public interface DataSource { 35 | int ERR_API_FAIL = 1; 36 | 37 | @ObjectiveCName("getWindowsWithPage:num:callback:") 38 | void getWindows(int page, int num, Callback> callback); 39 | 40 | /** 41 | * Contract: must be invoked at UI thread. 42 | */ 43 | interface Callback { 44 | @ObjectiveCName("onSuccess:") 45 | void onSuccess(D data); 46 | 47 | @ObjectiveCName("onFailure:") 48 | void onFailure(int error); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/java/com/github/piasy/java_universe/GuiWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | import com.google.j2objc.annotations.ObjectiveCName; 28 | 29 | /** 30 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 31 | */ 32 | 33 | public interface GuiWrapper { 34 | @ObjectiveCName("createViewWithWindow:") 35 | void createView(Window window); 36 | 37 | @ObjectiveCName("swapViewWithWindow:andWindow:") 38 | void swapView(Window alice, Window bob); 39 | 40 | void clearView(); 41 | } 42 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/java/com/github/piasy/java_universe/TextUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | /** 28 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 29 | */ 30 | 31 | public class TextUtils { 32 | public static boolean equals(String a, String b) { 33 | return a == b || (a != null && b != null && a.equals(b)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/java/com/github/piasy/java_universe/Window.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | import com.google.j2objc.annotations.ObjectiveCName; 28 | import com.google.j2objc.annotations.Property; 29 | 30 | /** 31 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 32 | */ 33 | 34 | public class Window { 35 | 36 | public static final int MATCH_PARENT = 10000; 37 | 38 | /** 39 | * width : 90 40 | * height : 160 41 | * top : 0 42 | * left : 0 43 | * z_index : 1 44 | * uid : knuth 45 | */ 46 | 47 | // all dimensions are percentage scaled by MATCH_PARENT(10000) 48 | @Property 49 | private int width; 50 | @Property 51 | private int height; 52 | @Property 53 | private int top; 54 | @Property 55 | private int left; 56 | @Property 57 | private int z_index; 58 | @Property 59 | private String uid; 60 | 61 | public Window() { 62 | } 63 | 64 | @ObjectiveCName("initWithWidth:height:top:left:zIndex:uid:") 65 | public Window(int width, int height, int top, int left, int z_index, String uid) { 66 | this.width = width; 67 | this.height = height; 68 | this.top = top; 69 | this.left = left; 70 | this.z_index = z_index; 71 | this.uid = uid; 72 | } 73 | 74 | public boolean isFullscreen() { 75 | return width == MATCH_PARENT && height == MATCH_PARENT; 76 | } 77 | 78 | public Window copy() { 79 | return new Window(width, height, top, left, z_index, uid); 80 | } 81 | 82 | @ObjectiveCName("swapWithWindow:") 83 | public void swap(Window that) { 84 | int tmp = top; 85 | top = that.top; 86 | that.top = tmp; 87 | 88 | tmp = left; 89 | left = that.left; 90 | that.left = tmp; 91 | 92 | tmp = width; 93 | width = that.width; 94 | that.width = tmp; 95 | 96 | tmp = height; 97 | height = that.height; 98 | that.height = tmp; 99 | 100 | tmp = z_index; 101 | z_index = that.z_index; 102 | that.z_index = tmp; 103 | } 104 | 105 | public int getWidth() { 106 | return width; 107 | } 108 | 109 | public void setWidth(int width) { 110 | this.width = width; 111 | } 112 | 113 | public int getHeight() { 114 | return height; 115 | } 116 | 117 | public void setHeight(int height) { 118 | this.height = height; 119 | } 120 | 121 | public int getTop() { 122 | return top; 123 | } 124 | 125 | public void setTop(int top) { 126 | this.top = top; 127 | } 128 | 129 | public int getLeft() { 130 | return left; 131 | } 132 | 133 | public void setLeft(int left) { 134 | this.left = left; 135 | } 136 | 137 | public int getZ_index() { 138 | return z_index; 139 | } 140 | 141 | public void setZ_index(int z_index) { 142 | this.z_index = z_index; 143 | } 144 | 145 | public String getUid() { 146 | return uid; 147 | } 148 | 149 | public void setUid(String uid) { 150 | this.uid = uid; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /JavaUniverse/src/main/java/com/github/piasy/java_universe/WindowManagerCore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe; 26 | 27 | import com.google.j2objc.annotations.ObjectiveCName; 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | /** 32 | * Created by Piasy{github.com/Piasy} on 08/11/2017. 33 | */ 34 | 35 | public class WindowManagerCore { 36 | private final DataSource mDataSource; 37 | private final GuiWrapper mGuiWrapper; 38 | private final Callback mCallback; 39 | 40 | private final List mWindows = new ArrayList<>(); 41 | 42 | public WindowManagerCore(final DataSource dataSource, final GuiWrapper guiWrapper, 43 | final Callback callback) { 44 | mDataSource = dataSource; 45 | mGuiWrapper = guiWrapper; 46 | mCallback = callback; 47 | } 48 | 49 | public void loadWindows() { 50 | mDataSource.getWindows(1, 20, new DataSource.Callback>() { 51 | @Override 52 | public void onSuccess(final List data) { 53 | mGuiWrapper.clearView(); 54 | mWindows.clear(); 55 | mWindows.addAll(data); 56 | 57 | final int size = mWindows.size(); 58 | for (int i = 0; i < size; i++) { 59 | mGuiWrapper.createView(mWindows.get(i)); 60 | } 61 | for (int i = 0; i < size; i++) { 62 | mCallback.onWindowAdded(mWindows.get(i).copy()); 63 | } 64 | } 65 | 66 | @Override 67 | public void onFailure(final int error) { 68 | mCallback.onError(error); 69 | } 70 | }); 71 | } 72 | 73 | public List getWindows() { 74 | List windows = new ArrayList<>(mWindows.size()); 75 | final int size = mWindows.size(); 76 | for (int i = 0; i < size; i++) { 77 | windows.add(mWindows.get(i).copy()); 78 | } 79 | return windows; 80 | } 81 | 82 | public void toggleFullscreen(String uid) { 83 | Window newFc = getWindowOf(uid); 84 | Window oldFc = getCurrentFullscreen(); 85 | if (newFc != null && oldFc != null && newFc != oldFc) { 86 | mGuiWrapper.swapView(newFc, oldFc); 87 | } 88 | } 89 | 90 | private Window getWindowOf(final String uid) { 91 | final int size = mWindows.size(); 92 | for (int i = 0; i < size; i++) { 93 | if (TextUtils.equals(mWindows.get(i).getUid(), uid)) { 94 | return mWindows.get(i); 95 | } 96 | } 97 | 98 | return null; 99 | } 100 | 101 | private Window getCurrentFullscreen() { 102 | final int size = mWindows.size(); 103 | for (int i = 0; i < size; i++) { 104 | if (mWindows.get(i).isFullscreen()) { 105 | return mWindows.get(i); 106 | } 107 | } 108 | 109 | return null; 110 | } 111 | 112 | public interface Callback { 113 | @ObjectiveCName("onWindowAdded:") 114 | void onWindowAdded(Window window); 115 | 116 | @ObjectiveCName("onError:") 117 | void onError(int error); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Piasy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '8.0' 3 | 4 | target 'JavaUniverse-iOS' do 5 | pod 'AFNetworking', '~> 3.0' 6 | end 7 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (3.1.0): 3 | - AFNetworking/NSURLSession (= 3.1.0) 4 | - AFNetworking/Reachability (= 3.1.0) 5 | - AFNetworking/Security (= 3.1.0) 6 | - AFNetworking/Serialization (= 3.1.0) 7 | - AFNetworking/UIKit (= 3.1.0) 8 | - AFNetworking/NSURLSession (3.1.0): 9 | - AFNetworking/Reachability 10 | - AFNetworking/Security 11 | - AFNetworking/Serialization 12 | - AFNetworking/Reachability (3.1.0) 13 | - AFNetworking/Security (3.1.0) 14 | - AFNetworking/Serialization (3.1.0) 15 | - AFNetworking/UIKit (3.1.0): 16 | - AFNetworking/NSURLSession 17 | 18 | DEPENDENCIES: 19 | - AFNetworking (~> 3.0) 20 | 21 | SPEC CHECKSUMS: 22 | AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67 23 | 24 | PODFILE CHECKSUM: 3d83c532355b89eae66ae0aa07ce826c8e744470 25 | 26 | COCOAPODS: 1.3.1 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaUniverse 2 | 3 | A demo project that showcase how to use Java to conquer the universe, with the help of 4 | [J2ObjC](https://developers.google.com/j2objc/) and [GWT](http://www.gwtproject.org/) :) 5 | 6 | This demo is a window management app, it download window configuration (size and position) 7 | from the Internet, then create TextView/UILabel from it, and user can switch fullscreen 8 | window. 9 | 10 | The window management logic and data structure is written in Java, but GUI operation and 11 | third party library call are written "natively", which is separated through interface/protocol. 12 | 13 | Web app is still working in progress... 14 | 15 | ## J2Objc Caveat 16 | 17 | + When modify build settings, don't forget add `$(inherited)` at first, otherwise CocoaPods 18 | will break. 19 | 20 | ## Xcode project file management 21 | 22 | + Use [xcake](https://github.com/jcampbell05/xcake) to generate Xcode project files, but 23 | J2ObjC need to use custom build rule, which is not supported by xcake yet, currently I 24 | use [my fork](https://github.com/Piasy/xcake), please track 25 | [this pr](https://github.com/jcampbell05/xcake/pull/181). 26 | + xcake can work with [CocoaPods](https://github.com/CocoaPods/CocoaPods), use 27 | `setup_xcode_project.sh` to setup Xcode project. 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.jakewharton.butterknife' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.androidCompileSdkVersion 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode rootProject.ext.releaseVersionCode 11 | versionName rootProject.ext.releaseVersionName 12 | 13 | applicationId "com.github.piasy.java_universe.example" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation "com.android.support:appcompat-v7:$rootProject.ext.androidSupportSdkVersion" 25 | 26 | implementation 'com.jakewharton:butterknife:9.0.0-SNAPSHOT' 27 | annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-SNAPSHOT' 28 | 29 | implementation project(':JavaUniverse') 30 | } 31 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/piasy/java_universe/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Piasy 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.github.piasy.java_universe.example; 26 | 27 | import android.os.Bundle; 28 | import android.support.v7.app.AppCompatActivity; 29 | import android.widget.FrameLayout; 30 | import android.widget.Toast; 31 | import butterknife.BindView; 32 | import butterknife.ButterKnife; 33 | import butterknife.OnClick; 34 | import com.github.piasy.java_universe.Window; 35 | import com.github.piasy.java_universe.WindowManager; 36 | import java.util.ArrayList; 37 | import java.util.List; 38 | 39 | public class MainActivity extends AppCompatActivity implements WindowManager.Callback { 40 | 41 | @BindView(R.id.mContainer) 42 | FrameLayout mContainer; 43 | 44 | private final List mUsers = new ArrayList<>(); 45 | 46 | private WindowManager mWindowManager; 47 | private int mFcIndex = 0; 48 | 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) { 51 | super.onCreate(savedInstanceState); 52 | setContentView(R.layout.activity_main); 53 | 54 | ButterKnife.bind(this); 55 | 56 | mWindowManager = new WindowManager(mContainer, this); 57 | 58 | mWindowManager.loadWindows(); 59 | } 60 | 61 | @OnClick(R.id.mShuffle) 62 | void shuffle() { 63 | mFcIndex = (mFcIndex + 1) % mUsers.size(); 64 | mWindowManager.toggleFullscreen(mUsers.get(mFcIndex)); 65 | } 66 | 67 | @Override 68 | public void onWindowAdded(final Window window) { 69 | mUsers.add(window.getUid()); 70 | } 71 | 72 | @Override 73 | public void onError(final int error) { 74 | Toast.makeText(this, "onError " + error, Toast.LENGTH_SHORT).show(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 14 | 15 | 22 | 26 | 30 | 31 | 32 | 33 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 13 | 19 | 25 | 31 | 37 | 43 | 49 | 55 | 61 | 67 | 73 | 79 | 85 | 91 | 97 | 103 | 109 | 115 | 121 | 127 | 133 | 139 | 145 | 151 | 157 | 163 | 169 | 175 | 181 | 187 | 193 | 199 | 205 | 206 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 |