├── .gitignore
├── README.md
├── android
├── AndroidManifest.xml
├── assets
│ ├── launcher.png
│ ├── music.jpg
│ ├── vedio.jpg
│ └── weather.jpg
├── build.gradle
├── ic_launcher-web.png
├── proguard-project.txt
├── project.properties
├── res
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── meizu
│ └── taskmanager
│ └── android
│ └── AndroidLauncher.java
├── build.gradle
├── core
├── build.gradle
└── src
│ ├── TaskManager.gwt.xml
│ └── com
│ └── meizu
│ └── taskmanager
│ ├── PagerStage.java
│ ├── TaskActor.java
│ ├── TaskItem.java
│ ├── TaskManager.java
│ ├── policy
│ ├── BackgroundService.java
│ └── ManagerService.java
│ ├── ui
│ ├── HorizontalGroup.java
│ └── ScrollPane.java
│ └── utils
│ ├── action
│ └── CancelableAction.java
│ ├── animation
│ ├── FloatEvaluator.java
│ ├── IntEvaluator.java
│ └── TypeEvaluator.java
│ └── eventbus
│ └── EventBusUtil.java
├── desktop
├── build.gradle
└── src
│ └── com
│ └── meizu
│ └── taskmanager
│ └── desktop
│ └── DesktopLauncher.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── html
├── build.gradle
├── src
│ └── com
│ │ └── meizu
│ │ └── taskmanager
│ │ ├── GdxDefinition.gwt.xml
│ │ ├── GdxDefinitionSuperdev.gwt.xml
│ │ └── client
│ │ └── HtmlLauncher.java
└── webapp
│ ├── WEB-INF
│ └── web.xml
│ ├── index.html
│ ├── refresh.png
│ ├── soundmanager2-jsmin.js
│ ├── soundmanager2-setup.js
│ └── styles.css
├── screen-record.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Java
2 |
3 | *.class
4 | *.war
5 | *.ear
6 | hs_err_pid*
7 |
8 | ## GWT
9 | war/
10 | html/war/gwt_bree/
11 | html/gwt-unitCache/
12 | .apt_generated/
13 | html/war/WEB-INF/deploy/
14 | html/war/WEB-INF/classes/
15 | .gwt/
16 | gwt-unitCache/
17 | www-test/
18 | .gwt-tmp/
19 |
20 | ## Android Studio and Intellij and Android in general
21 | android/libs/armeabi/
22 | android/libs/armeabi-v7a/
23 | android/libs/x86/
24 | android/gen/
25 | .idea/
26 | *.ipr
27 | *.iws
28 | *.iml
29 | out/
30 | com_crashlytics_export_strings.xml
31 |
32 | ## Eclipse
33 | .classpath
34 | .project
35 | .metadata
36 | **/bin/
37 | tmp/
38 | *.tmp
39 | *.bak
40 | *.swp
41 | *~.nib
42 | local.properties
43 | .settings/
44 | .loadpath
45 | .externalToolBuilders/
46 | *.launch
47 |
48 | ## NetBeans
49 | **/nbproject/private/
50 | build/
51 | nbbuild/
52 | dist/
53 | nbdist/
54 | nbactions.xml
55 | nb-configuration.xml
56 |
57 | ## Gradle
58 |
59 | .gradle
60 | gradle-app.setting
61 | build/
62 |
63 | ## OS Specific
64 | .DS_Store
65 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TaskManager
2 |
3 | ----
4 |
5 | 
6 |
7 | 恕我脑残,之前移除了对桌面应用的支持。重新加回桌面应用的支持和html的支持!
8 |
9 | 初步规则如下:
10 |
11 | 1、优先在桌面应用的模式下进行调试,效率大幅提升(cd desktop && gradle runDesktop);
12 |
13 | 2、所有的代码放于core目录下;
14 |
15 | 3、用core下的policy目录模拟多任务的真实场景,后期再迁回android/desktop/html目录;
16 |
17 |
18 | running or debugging:
19 |
20 | Desktop: Run -> Edit Configurations..., click the plus (+) button and select Application. Set the Nameto Desktop.Set the field Use classpath of module to desktop, then click on the button of the Main class field and select the DesktopLauncher class. Set the Working directory to your android/assets/ (or your_project_path/core/assets/) folder! Click Apply and then OK. You have now created a run configuration for your desktop project. You can now select the configuration and run it.
21 |
22 | Android: A configuration for the Android project should be automatically created on project import. As such, you only have to select the configuration and run it!
23 |
24 | iOS: Run -> Edit Configurations..., click the plus (+) button and select Gradle. Set the Name to iOS, set the Gradle Project to ios, set the Tasks to launchIPhoneSimulator (alternatives are launchIPadSimulator and launchIOSDevicefor provisioned devices). Click Apply and then OK. You have now created a run configuration for your iOS project. You can now select the configuration and run it. The first run will take a bit longer as RoboVM has to compile the entire JDK for iOS. Subsequent runs will compile considerably faster!
25 |
26 | HTML: View -> Tool Window -> Terminal, in the terminal, make sure you are in the root folder of your project. Then execute gradlew.bat html:superDev (Windows) or ./gradlew html:superDev (Linux, Mac OS X). This will take a while, as your Java code is compiled to Javascript. Once you see the message The code server is ready, fire up your browser and go to http://localhost:8080/html. This is your app running in the browser! When you change any of your Java code or assets, just click the SuperDev refresh button while you are on the site and the server will recompile your code and reload the page! To kill the process, simply press CTRL + C in the terminal window.
27 |
--------------------------------------------------------------------------------
/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/android/assets/launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/assets/launcher.png
--------------------------------------------------------------------------------
/android/assets/music.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/assets/music.jpg
--------------------------------------------------------------------------------
/android/assets/vedio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/assets/vedio.jpg
--------------------------------------------------------------------------------
/android/assets/weather.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/assets/weather.jpg
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | android {
2 | buildToolsVersion "21.1.2"
3 | compileSdkVersion 21
4 | sourceSets {
5 | main {
6 | manifest.srcFile 'AndroidManifest.xml'
7 | java.srcDirs = ['src']
8 | aidl.srcDirs = ['src']
9 | renderscript.srcDirs = ['src']
10 | res.srcDirs = ['res']
11 | assets.srcDirs = ['assets']
12 | }
13 |
14 | instrumentTest.setRoot('tests')
15 | }
16 | }
17 |
18 | // needed to add JNI shared libraries to APK when compiling on CLI
19 | tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
20 | pkgTask.jniFolders = new HashSet()
21 | pkgTask.jniFolders.add(new File(projectDir, 'libs'))
22 | }
23 |
24 | // called every time gradle gets executed, takes the native dependencies of
25 | // the natives configuration, and extracts them to the proper libs/ folders
26 | // so they get packed with the APK.
27 | task copyAndroidNatives() {
28 | file("libs/armeabi/").mkdirs();
29 | file("libs/armeabi-v7a/").mkdirs();
30 | file("libs/x86/").mkdirs();
31 |
32 | configurations.natives.files.each { jar ->
33 | def outputDir = null
34 | if(jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a")
35 | if(jar.name.endsWith("natives-armeabi.jar")) outputDir = file("libs/armeabi")
36 | if(jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86")
37 | if(outputDir != null) {
38 | copy {
39 | from zipTree(jar)
40 | into outputDir
41 | include "*.so"
42 | }
43 | }
44 | }
45 | }
46 |
47 | task run(type: Exec) {
48 | def path
49 | def localProperties = project.file("../local.properties")
50 | if (localProperties.exists()) {
51 | Properties properties = new Properties()
52 | localProperties.withInputStream { instr ->
53 | properties.load(instr)
54 | }
55 | def sdkDir = properties.getProperty('sdk.dir')
56 | if (sdkDir) {
57 | path = sdkDir
58 | } else {
59 | path = "$System.env.ANDROID_HOME"
60 | }
61 | } else {
62 | path = "$System.env.ANDROID_HOME"
63 | }
64 |
65 | def adb = path + "/platform-tools/adb"
66 | commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.meizu.taskmanager.android/com.meizu.taskmanager.android.AndroidLauncher'
67 | }
68 |
69 | // sets up the Android Eclipse project, using the old Ant based build.
70 | eclipse {
71 | // need to specify Java source sets explicitely, SpringSource Gradle Eclipse plugin
72 | // ignores any nodes added in classpath.file.withXml
73 | sourceSets {
74 | main {
75 | java.srcDirs "src", 'gen'
76 | }
77 | }
78 |
79 | jdt {
80 | sourceCompatibility = 1.6
81 | targetCompatibility = 1.6
82 | }
83 |
84 | classpath {
85 | plusConfigurations += [ project.configurations.compile ]
86 | containers 'com.android.ide.eclipse.adt.ANDROID_FRAMEWORK', 'com.android.ide.eclipse.adt.LIBRARIES'
87 | }
88 |
89 | project {
90 | name = appName + "-android"
91 | natures 'com.android.ide.eclipse.adt.AndroidNature'
92 | buildCommands.clear();
93 | buildCommand "com.android.ide.eclipse.adt.ResourceManagerBuilder"
94 | buildCommand "com.android.ide.eclipse.adt.PreCompilerBuilder"
95 | buildCommand "org.eclipse.jdt.core.javabuilder"
96 | buildCommand "com.android.ide.eclipse.adt.ApkBuilder"
97 | }
98 | }
99 |
100 | // sets up the Android Idea project, using the old Ant based build.
101 | idea {
102 | module {
103 | sourceDirs += file("src");
104 | scopes = [ COMPILE: [plus:[project.configurations.compile]]]
105 |
106 | iml {
107 | withXml {
108 | def node = it.asNode()
109 | def builder = NodeBuilder.newInstance();
110 | builder.current = node;
111 | builder.component(name: "FacetManager") {
112 | facet(type: "android", name: "Android") {
113 | configuration {
114 | option(name: "UPDATE_PROPERTY_FILES", value:"true")
115 | }
116 | }
117 | }
118 | }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/android/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/ic_launcher-web.png
--------------------------------------------------------------------------------
/android/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
22 | -verbose
23 |
24 | -dontwarn android.support.**
25 | -dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication
26 | -dontwarn com.badlogic.gdx.utils.GdxBuild
27 | -dontwarn com.badlogic.gdx.physics.box2d.utils.Box2DBuild
28 | -dontwarn com.badlogic.gdx.jnigen.BuildTarget*
29 |
30 | -keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
31 | (com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
32 | }
33 |
34 | -keepclassmembers class com.badlogic.gdx.physics.box2d.World {
35 | boolean contactFilter(long, long);
36 | void beginContact(long);
37 | void endContact(long);
38 | void preSolve(long, long);
39 | void postSolve(long, long);
40 | boolean reportFixture(long);
41 | float reportRayFixture(long, float, float, float, float, float);
42 | }
43 |
--------------------------------------------------------------------------------
/android/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 |
--------------------------------------------------------------------------------
/android/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/android/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TaskManager
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/android/src/com/meizu/taskmanager/android/AndroidLauncher.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.android;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.badlogic.gdx.backends.android.AndroidApplication;
6 | import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
7 | import com.meizu.taskmanager.TaskManager;
8 |
9 | public class AndroidLauncher extends AndroidApplication {
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
14 | config.disableAudio = true;
15 | config.useAccelerometer = false;
16 | config.useGLSurfaceView20API18 = true;
17 | initialize(new TaskManager(), config);
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
8 | classpath 'com.android.tools.build:gradle:1.0.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | apply plugin: "eclipse"
14 | apply plugin: "idea"
15 |
16 | version = '1.0'
17 | ext {
18 | appName = 'TaskManager'
19 | gdxVersion = '1.5.3'
20 | roboVMVersion = '1.0.0-beta-03'
21 | box2DLightsVersion = '1.3'
22 | ashleyVersion = '1.3.1'
23 | aiVersion = '1.5.0'
24 | }
25 |
26 | repositories {
27 | mavenCentral()
28 | maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
29 | maven { url "https://oss.sonatype.org/content/repositories/releases/" }
30 | }
31 | }
32 |
33 | project(":desktop") {
34 | apply plugin: "java"
35 |
36 |
37 | dependencies {
38 | compile project(":core")
39 | compile "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
40 | compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
41 | compile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
42 | }
43 | }
44 |
45 | project(":android") {
46 | apply plugin: "android"
47 |
48 | configurations { natives }
49 |
50 | dependencies {
51 | compile project(":core")
52 | compile "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion"
53 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi"
54 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a"
55 | natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86"
56 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
57 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi"
58 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-armeabi-v7a"
59 | natives "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-x86"
60 | }
61 | }
62 |
63 | project(":html") {
64 | apply plugin: "gwt"
65 | apply plugin: "war"
66 |
67 |
68 | dependencies {
69 | compile project(":core")
70 | compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion"
71 | compile "com.badlogicgames.gdx:gdx:$gdxVersion:sources"
72 | compile "com.badlogicgames.gdx:gdx-backend-gwt:$gdxVersion:sources"
73 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion:sources"
74 | compile "com.badlogicgames.gdx:gdx-box2d-gwt:$gdxVersion:sources"
75 | }
76 | }
77 |
78 | project(":core") {
79 | apply plugin: "java"
80 |
81 |
82 | dependencies {
83 | compile "com.badlogicgames.gdx:gdx:$gdxVersion"
84 | compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
85 | compile "com.google.guava:guava:+"
86 | }
87 | }
88 |
89 | tasks.eclipse.doLast {
90 | delete ".project"
91 | }
--------------------------------------------------------------------------------
/core/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 |
3 | sourceCompatibility = 1.7
4 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
5 |
6 | sourceSets.main.java.srcDirs = [ "src/" ]
7 |
8 |
9 | eclipse.project {
10 | name = appName + "-core"
11 | }
12 |
--------------------------------------------------------------------------------
/core/src/TaskManager.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/PagerStage.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.input.GestureDetector;
5 | import com.badlogic.gdx.math.Interpolation;
6 | import com.badlogic.gdx.math.Vector2;
7 | import com.badlogic.gdx.scenes.scene2d.Action;
8 | import com.badlogic.gdx.scenes.scene2d.Actor;
9 | import com.badlogic.gdx.scenes.scene2d.Stage;
10 | import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction;
11 | import com.badlogic.gdx.utils.SnapshotArray;
12 | import com.google.common.eventbus.Subscribe;
13 | import com.meizu.taskmanager.ui.HorizontalGroup;
14 | import com.meizu.taskmanager.utils.action.CancelableAction;
15 | import com.meizu.taskmanager.utils.animation.FloatEvaluator;
16 | import com.meizu.taskmanager.utils.eventbus.EventBusUtil;
17 |
18 |
19 | public class PagerStage extends Stage {
20 |
21 | public final static class UpdateRectEvent {
22 | }
23 |
24 | public final static class Rect {
25 | public final float x;
26 | public final float y;
27 | public final float width;
28 | public final float height;
29 | public final float center;
30 |
31 | public Rect(float x, float y, float width, float height) {
32 | this.x = x;
33 | this.y = y;
34 | this.width = width;
35 | this.height = height;
36 | this.center = x + width / 2;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return "Rect{" +
42 | "center=" + center +
43 | '}';
44 | }
45 | }
46 |
47 | public GestureDetector.GestureListener flickScrollListener;
48 |
49 | private Rect[] mRect;
50 | private float mCameraPosition;
51 | private HorizontalGroup mGroup;
52 | private CancelableAction mMoveCameraAction;
53 |
54 | public PagerStage() {
55 | super();
56 | mCameraPosition = getCamera().position.x;
57 | flickScrollListener = new GestureDetector.GestureListener() {
58 | short focusThis;
59 |
60 | @Override
61 | public boolean touchDown(float x, float y, int pointer, int button) {
62 | focusThis = 0;
63 | cancelMoveIfNeed();
64 | return false;
65 | }
66 |
67 | @Override
68 | public boolean tap(float x, float y, int count, int button) {
69 | return false;
70 | }
71 |
72 | @Override
73 | public boolean longPress(float x, float y) {
74 | return false;
75 | }
76 |
77 | @Override
78 | public boolean fling(float velocityX, float velocityY, int button) {
79 | if (focusThis == 1) {
80 | addAction(new ScrollCameraAction(0.5f, Interpolation.linear).setToPotion(calm(mCameraPosition - velocityX)));
81 | return true;
82 | }
83 | return false;
84 | }
85 |
86 | @Override
87 | public boolean pan(float x, float y, float deltaX, float deltaY) {
88 | if (focusThis == 0) {
89 | if (Math.abs(deltaX) > Math.abs(deltaY)) {
90 | focusThis = 1;
91 | cancelTouchFocus();
92 | return true;
93 | } else {
94 | focusThis = -1;
95 | return false;
96 | }
97 |
98 | } else if (focusThis == 1) {
99 | addAction(new MoveCameraAction().setOffset(-deltaX));
100 | return true;
101 | } else {
102 | return false;
103 | }
104 | }
105 |
106 | @Override
107 | public boolean panStop(float x, float y, int pointer, int button) {
108 | if (focusThis == 1) {
109 | addAction(new ScrollCameraAction(0.2f, Interpolation.linear).setToPotion(calm(mCameraPosition)));
110 | return true;
111 | } else {
112 | return false;
113 | }
114 | }
115 |
116 | @Override
117 | public boolean zoom(float initialDistance, float distance) {
118 | return false;
119 | }
120 |
121 | @Override
122 | public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
123 | return false;
124 | }
125 | };
126 |
127 | EventBusUtil.getDefaultEventBus().register(this);
128 |
129 | }
130 |
131 | @Override
132 | public void dispose() {
133 | super.dispose();
134 | EventBusUtil.getDefaultEventBus().unregister(this);
135 | }
136 |
137 | public void bindGroup(HorizontalGroup group) {
138 | mGroup = group;
139 | }
140 |
141 | public float calm(float toPotion) {
142 | float reFloat = 0;
143 | float distance = Float.MAX_VALUE;
144 | for (int i = 0, n = mRect.length; i < n; i++) {
145 | final float dis = Math.abs(mRect[i].center - toPotion);
146 | if (dis < distance) {
147 | distance = dis;
148 | reFloat = mRect[i].center;
149 | }
150 | }
151 | return reFloat;
152 | }
153 |
154 | @Subscribe
155 | public void updateRect(UpdateRectEvent event) {
156 | updateRect();
157 | }
158 |
159 | public void updateRect() {
160 | SnapshotArray children = mGroup.getChildren();
161 | PagerStage.Rect[] rects = new PagerStage.Rect[children.size];
162 | for (int i = 0, n = rects.length; i < n; i++) {
163 | Actor actor = children.get(i);
164 |
165 | rects[i] = new PagerStage.Rect(actor.getX(), actor.getY(), actor.getWidth(), actor.getHeight());
166 | }
167 | mRect = rects;
168 |
169 |
170 | float calm = calm(mCameraPosition);
171 | if (calm != mCameraPosition)
172 | addAction(new ScrollCameraAction(0.2f, Interpolation.linear).setToPotion(calm));
173 | }
174 |
175 | public void init() {
176 | addAction(new MoveCameraAction().setOffset(mRect[0].center - mCameraPosition));
177 | }
178 |
179 | private void updateCameraToPotion(float toPotion) {
180 | mCameraPosition = toPotion;
181 | getCamera().position.set(mCameraPosition, Gdx.graphics.getHeight() / 2, getCamera().position.z);
182 | getCamera().update();
183 | }
184 |
185 | private void updateCameraOffset(float x) {
186 | mCameraPosition += x;
187 | getCamera().position.set(mCameraPosition, Gdx.graphics.getHeight() / 2, getCamera().position.z);
188 | getCamera().update();
189 | }
190 |
191 |
192 | private void cancelMoveIfNeed(){
193 | if (mMoveCameraAction != null) {
194 | mMoveCameraAction.cancel();
195 | }
196 | }
197 |
198 | private class MoveCameraAction extends Action {
199 |
200 | private float offset;
201 |
202 | public MoveCameraAction() {
203 | super();
204 | cancelMoveIfNeed();
205 | }
206 |
207 | public MoveCameraAction setOffset(float offset) {
208 | this.offset = offset;
209 | return this;
210 | }
211 |
212 | @Override
213 | public boolean act(float delta) {
214 | updateCameraOffset(offset);
215 | return true;
216 | }
217 |
218 | }
219 |
220 | private class ScrollCameraAction extends TemporalAction implements CancelableAction {
221 |
222 | FloatEvaluator floatEvaluator = new FloatEvaluator();
223 |
224 | @Override
225 | protected void end() {
226 | if (mMoveCameraAction == this) mMoveCameraAction = null;
227 | }
228 |
229 | private boolean alive = true;
230 |
231 | private float toPotion;
232 |
233 | private float originPotion;
234 |
235 | ScrollCameraAction(float duration, Interpolation interpolation) {
236 | super(duration, interpolation);
237 | cancelMoveIfNeed();
238 | mMoveCameraAction = this;
239 | }
240 |
241 |
242 | public ScrollCameraAction setToPotion(float toPotion) {
243 | this.originPotion = mCameraPosition;
244 | this.toPotion = toPotion;
245 | return this;
246 | }
247 |
248 |
249 | @Override
250 | protected void update(float percent) {
251 | if (!alive) return;
252 | updateCameraToPotion(floatEvaluator.evaluate(percent, originPotion, toPotion));
253 | }
254 |
255 | @Override
256 | public void cancel() {
257 | alive = false;
258 | }
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/TaskActor.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.graphics.g2d.Batch;
5 | import com.badlogic.gdx.graphics.g2d.Sprite;
6 | import com.badlogic.gdx.scenes.scene2d.Action;
7 | import com.badlogic.gdx.scenes.scene2d.Actor;
8 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
9 | import com.badlogic.gdx.scenes.scene2d.Stage;
10 | import com.badlogic.gdx.scenes.scene2d.actions.MoveByAction;
11 | import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;
12 | import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
13 | import com.meizu.taskmanager.utils.action.CancelableAction;
14 |
15 | public class TaskActor extends Actor {
16 | private Sprite mSprite;
17 |
18 | private CancelableAction mMoveAction;
19 |
20 | public TaskActor(TaskItem item) {
21 | addCaptureListener(actorGestureListener);
22 |
23 | final float zoom = Gdx.graphics.getWidth() * 0.6f / item.getScreenShot().getWidth();
24 |
25 | mSprite = new Sprite(item.getScreenShot());
26 | mSprite.setSize(mSprite.getWidth() * zoom, mSprite.getHeight() * zoom);
27 | setWidth(mSprite.getWidth());
28 | setHeight(mSprite.getHeight());
29 | }
30 |
31 | @Override
32 | public void draw(Batch batch, float parentAlpha) {
33 | mSprite.setPosition(getX(), getY());
34 | mSprite.draw(batch);
35 | }
36 |
37 | private ActorGestureListener actorGestureListener = new ActorGestureListener() {
38 | boolean catchFocus;
39 | float speed;
40 |
41 | @Override
42 | public void pan(InputEvent event, float x, float y, float deltaX, float deltaY) {
43 | Stage stage = getStage();
44 | if (!catchFocus && Math.abs(deltaX) < Math.abs(deltaY)) {
45 | catchFocus = true;
46 | if (stage != null)
47 | stage.cancelTouchFocusExcept(actorGestureListener, TaskActor.this);
48 | }
49 | if (catchFocus) {
50 | MoveByAction moveByAction = new MoveByAction();
51 | moveByAction.setAmountY(deltaY);
52 | addAction(moveByAction);
53 | }
54 | }
55 |
56 | @Override
57 | public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
58 | speed = 0;
59 | cancelMoveIfNeed();
60 | if (getOriginY() == 0) {
61 | setOriginY(getY());
62 | }
63 | super.touchDown(event, x, y, pointer, button);
64 | }
65 |
66 | @Override
67 | public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
68 |
69 | if ((Math.abs(speed) <= 150 && speed != 0) || (speed == 0 && getY() != getOriginY())) {
70 | MoveToOringinAction moveToAction = new MoveToOringinAction();
71 | moveToAction.setPosition(getX(), getOriginY());
72 | moveToAction.setDuration(0.5f);
73 | addAction(moveToAction);
74 | }
75 | super.touchUp(event, x, y, pointer, button);
76 | }
77 |
78 | @Override
79 | public void fling(InputEvent event, float velocityX, float velocityY, int button) {
80 | speed = velocityY;
81 |
82 | if (Math.abs(speed) > 150) {
83 | addAction(new RemoveTaskAction());
84 | } else {
85 | MoveToOringinAction moveToAction = new MoveToOringinAction();
86 | moveToAction.setPosition(getX(), getOriginY());
87 | moveToAction.setDuration(0.3f);
88 | addAction(moveToAction);
89 | }
90 | super.fling(event, velocityX, velocityY, button);
91 | }
92 | };
93 |
94 |
95 | private void cancelMoveIfNeed(){
96 | if (mMoveAction != null) {
97 | mMoveAction.cancel();
98 | }
99 | }
100 |
101 | private class MoveToOringinAction extends MoveToAction implements CancelableAction {
102 | boolean alive = true;
103 |
104 | public MoveToOringinAction() {
105 | cancelMoveIfNeed();
106 | mMoveAction = this;
107 | }
108 |
109 | @Override
110 | protected void end() {
111 | if (mMoveAction == this) mMoveAction = null;
112 | }
113 |
114 | @Override
115 | protected void update(float percent) {
116 | if (!alive) return;
117 | super.update(percent);
118 | }
119 |
120 | @Override
121 | public void cancel() {
122 | alive = false;
123 | }
124 | }
125 |
126 | private class RemoveTaskAction extends Action {
127 |
128 |
129 | public boolean act(float delta) {
130 | target.remove();
131 | return true;
132 | }
133 |
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/TaskItem.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager;
2 |
3 | import com.badlogic.gdx.graphics.Texture;
4 |
5 | public class TaskItem {
6 | private int id;
7 | private Texture screenShot;
8 | private Texture icon;
9 |
10 | public int getId() {
11 | return id;
12 | }
13 |
14 | public TaskItem setId(int id) {
15 | this.id = id;
16 | return this;
17 | }
18 |
19 | public Texture getScreenShot() {
20 | return screenShot;
21 | }
22 |
23 | public TaskItem setScreenShot(Texture screenShot) {
24 | this.screenShot = screenShot;
25 | return this;
26 | }
27 |
28 | public Texture getIcon() {
29 | return icon;
30 | }
31 |
32 | public TaskItem setIcon(Texture icon) {
33 | this.icon = icon;
34 | return this;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/TaskManager.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager;
2 |
3 | import com.badlogic.gdx.ApplicationListener;
4 | import com.badlogic.gdx.Gdx;
5 | import com.badlogic.gdx.InputMultiplexer;
6 | import com.badlogic.gdx.graphics.GL30;
7 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
8 | import com.badlogic.gdx.input.GestureDetector;
9 | import com.meizu.taskmanager.policy.BackgroundService;
10 | import com.meizu.taskmanager.policy.ManagerService;
11 | import com.meizu.taskmanager.ui.HorizontalGroup;
12 |
13 |
14 | public class TaskManager implements ApplicationListener {
15 | private PagerStage mStage;
16 | private SpriteBatch mBatch;
17 |
18 | @Override
19 | public void create() {
20 | mBatch = new SpriteBatch();
21 | mStage = new PagerStage();
22 |
23 | Gdx.graphics.setContinuousRendering(true);
24 |
25 | InputMultiplexer multiplexer = new InputMultiplexer(new GestureDetector(mStage.flickScrollListener), mStage);
26 | Gdx.input.setInputProcessor(multiplexer);
27 | }
28 |
29 | @Override
30 | public void resize(int width, int height) {
31 | pause();
32 | resume();
33 | }
34 |
35 | @Override
36 | public void render() {
37 | Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
38 |
39 | mBatch.begin();
40 | mBatch.draw(BackgroundService.getBackGround(), 0, 0);
41 | mBatch.end();
42 | mStage.act(Gdx.graphics.getDeltaTime());
43 | mStage.draw();
44 | }
45 |
46 | @Override
47 | public void pause() {
48 | mStage.clear();
49 | }
50 |
51 | @Override
52 | public void resume() {
53 |
54 | HorizontalGroup mGroup = new HorizontalGroup();
55 | mGroup.space(50f);
56 | mGroup.setBounds(0, 0, mStage.getWidth(), mStage.getHeight());
57 | final TaskItem[] taskItems = ManagerService.getTaskItem();
58 | for (int i = 0; i < taskItems.length; i++) {
59 | mGroup.addActor(new TaskActor(taskItems[i]));
60 | }
61 | mGroup.layout();
62 | mStage.addActor(mGroup);
63 | mStage.bindGroup(mGroup);
64 | mStage.updateRect();
65 | mStage.init();
66 |
67 | }
68 |
69 | @Override
70 | public void dispose() {
71 | mStage.dispose();
72 | mStage = null;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/policy/BackgroundService.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.policy;
2 |
3 | import com.badlogic.gdx.graphics.Texture;
4 |
5 | public class BackgroundService {
6 | private static Texture background;
7 |
8 | public synchronized static final Texture getBackGround() {
9 | if (background == null) background = new Texture("launcher.png");
10 | return background;
11 | }
12 | }
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/policy/ManagerService.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.policy;
2 |
3 | import com.badlogic.gdx.graphics.Texture;
4 | import com.meizu.taskmanager.TaskItem;
5 |
6 | public class ManagerService {
7 | static TaskItem[] taskItems;
8 |
9 | public static void kill(){
10 |
11 | }
12 |
13 | public static TaskItem[] getTaskItem() {
14 | if (taskItems == null) {
15 | taskItems = new TaskItem[18];
16 | Texture texture1 = new Texture("music.jpg");
17 | Texture texture2 = new Texture("vedio.jpg");
18 | Texture texture3 = new Texture("weather.jpg");
19 |
20 | for (int i = 0; i < taskItems.length; i++) {
21 | double random = Math.random();
22 | if (random < 0.3) {
23 | taskItems[i] = new TaskItem().setScreenShot(texture1);
24 | } else if (random < 0.6) {
25 | taskItems[i] = new TaskItem().setScreenShot(texture2);
26 | } else {
27 | taskItems[i] = new TaskItem().setScreenShot(texture3);
28 | }
29 | }
30 | }
31 | return taskItems;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/ui/HorizontalGroup.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.meizu.taskmanager.ui;
18 |
19 | import com.badlogic.gdx.math.Interpolation;
20 | import com.badlogic.gdx.scenes.scene2d.Actor;
21 | import com.badlogic.gdx.scenes.scene2d.Touchable;
22 | import com.badlogic.gdx.scenes.scene2d.actions.TemporalAction;
23 | import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
24 | import com.badlogic.gdx.scenes.scene2d.utils.Align;
25 | import com.badlogic.gdx.scenes.scene2d.utils.Layout;
26 | import com.badlogic.gdx.utils.SnapshotArray;
27 | import com.google.common.eventbus.EventBus;
28 | import com.meizu.taskmanager.PagerStage;
29 | import com.meizu.taskmanager.utils.eventbus.EventBusUtil;
30 |
31 | /** A group that lays out its children side by side in a single row. This can be easier than using {@link com.badlogic.gdx.scenes.scene2d.ui.Table} when actors need
32 | * to be inserted in the middle of the group.
33 | *
34 | * The preferred width is the sum of the children's preferred widths, plus spacing if set. The preferred height is the largest
35 | * preferred height of any child. The min size is the preferred size and the max size is 0 as HorizontalGroup can be
36 | * stretched to cover any area.
37 | *
38 | * This UI widget does not support Layoutable actors that return 0 as their preferred width. A fine example is
39 | * {@link com.badlogic.gdx.scenes.scene2d.ui.Label} class with text wrapping turned on.
40 | * @author Nathan Sweet */
41 | public class HorizontalGroup extends WidgetGroup {
42 | private float prefWidth, prefHeight;
43 | private boolean sizeInvalid = true;
44 | private int align;
45 | private boolean reverse, round = true;
46 | private float spacing;
47 | private float padTop, padLeft, padBottom, padRight;
48 | private float fill;
49 |
50 | public HorizontalGroup () {
51 | setTouchable(Touchable.childrenOnly);
52 | }
53 |
54 | public void invalidate () {
55 | super.invalidate();
56 | sizeInvalid = true;
57 | }
58 |
59 | private void computeSize () {
60 | sizeInvalid = false;
61 | SnapshotArray children = getChildren();
62 | int n = children.size;
63 | prefWidth = padLeft + padRight + spacing * (n - 1);
64 | prefHeight = 0;
65 | for (int i = 0; i < n; i++) {
66 | Actor child = children.get(i);
67 | if (child instanceof Layout) {
68 | Layout layout = (Layout)child;
69 | prefWidth += layout.getPrefWidth();
70 | prefHeight = Math.max(prefHeight, layout.getPrefHeight());
71 | } else {
72 | prefWidth += child.getWidth();
73 | prefHeight = Math.max(prefHeight, child.getHeight());
74 | }
75 | }
76 | prefHeight += padTop + padBottom;
77 | if (round) {
78 | prefWidth = Math.round(prefWidth);
79 | prefHeight = Math.round(prefHeight);
80 | }
81 | }
82 |
83 | int mChildNumber =0;
84 | @Override
85 | protected void childrenChanged() {
86 | int locChildNumber = getChildren().size;
87 | if(locChildNumber children = getChildren();
124 |
125 | @Override
126 | protected void begin() {
127 | super.begin();
128 | fromX=new float[children.size];
129 | toX=new float[children.size];
130 | for(int i = 0, n = children.size; i < n; i++){
131 | Actor child=children.get(i);
132 | fromX[i]=child.getX();
133 |
134 | float width, height;
135 | if (child instanceof Layout) {
136 | Layout layout = (Layout)child;
137 | if (fill > 0)
138 | height = groupHeight * fill;
139 | else
140 | height = Math.min(layout.getPrefHeight(), groupHeight);
141 | height = Math.max(height, layout.getMinHeight());
142 | float maxHeight = layout.getMaxHeight();
143 | if (maxHeight > 0 && height > maxHeight) height = maxHeight;
144 | width = layout.getPrefWidth();
145 | } else {
146 | width = child.getWidth();
147 | height = child.getHeight();
148 | if (fill > 0) height *= fill;
149 | }
150 |
151 | float y = padBottom;
152 | if ((align & Align.top) != 0)
153 | y += groupHeight - height;
154 | else if ((align & Align.bottom) == 0) // center
155 | y += (groupHeight - height) / 2;
156 |
157 | if (reverse) x -= (width + spacing);
158 | if (round)
159 | toX[i]=Math.round(x);
160 | else
161 | toX[i]=x;
162 | if (!reverse) x += (width + spacing);
163 |
164 | maxDistanse=Math.max(fromX[i]-toX[i],maxDistanse);
165 | }
166 | if(maxDistanse==0){
167 | setDuration(0);
168 | }
169 | }
170 |
171 | @Override
172 | protected void update(float percent) {
173 | for (int i = 0, n = children.size; i < n; i++) {
174 | Actor child = children.get(i);
175 | child.setX(toX[i]+(fromX[i]-toX[i])*(1-percent));
176 | }
177 | }
178 |
179 | @Override
180 | protected void end() {
181 | super.end();
182 | layout();
183 |
184 |
185 | EventBusUtil.getDefaultEventBus().post(new PagerStage.UpdateRectEvent());
186 | mChildChangeAction=null;
187 | }
188 | }
189 |
190 | public void layout () {
191 | float spacing = this.spacing, padBottom = this.padBottom;
192 | int align = this.align;
193 | boolean reverse = this.reverse, round = this.round;
194 |
195 | float groupHeight = getHeight() - padTop - padBottom;
196 | float x = !reverse ? padLeft : getWidth() - padRight + spacing;
197 | SnapshotArray children = getChildren();
198 | for (int i = 0, n = children.size; i < n; i++) {
199 | Actor child = children.get(i);
200 | float width, height;
201 | if (child instanceof Layout) {
202 | Layout layout = (Layout)child;
203 | if (fill > 0)
204 | height = groupHeight * fill;
205 | else
206 | height = Math.min(layout.getPrefHeight(), groupHeight);
207 | height = Math.max(height, layout.getMinHeight());
208 | float maxHeight = layout.getMaxHeight();
209 | if (maxHeight > 0 && height > maxHeight) height = maxHeight;
210 | width = layout.getPrefWidth();
211 | } else {
212 | width = child.getWidth();
213 | height = child.getHeight();
214 | if (fill > 0) height *= fill;
215 | }
216 |
217 | float y = padBottom;
218 | if ((align & Align.top) != 0)
219 | y += groupHeight - height;
220 | else if ((align & Align.bottom) == 0) // center
221 | y += (groupHeight - height) / 2;
222 |
223 | if (reverse) x -= (width + spacing);
224 | if (round)
225 | child.setBounds(Math.round(x), Math.round(y), Math.round(width), Math.round(height));
226 | else
227 | child.setBounds(x, y, width, height);
228 | if (!reverse) x += (width + spacing);
229 | }
230 | }
231 |
232 | public float getPrefWidth () {
233 | if (sizeInvalid) computeSize();
234 | return prefWidth;
235 | }
236 |
237 | public float getPrefHeight () {
238 | if (sizeInvalid) computeSize();
239 | return prefHeight;
240 | }
241 |
242 | /** If true (the default), positions and sizes are rounded to integers. */
243 | public void setRound (boolean round) {
244 | this.round = round;
245 | }
246 |
247 | /** The children will be ordered from right to left rather than the default left to right. */
248 | public HorizontalGroup reverse () {
249 | reverse(true);
250 | return this;
251 | }
252 |
253 | /** If true, the children will be ordered from right to left rather than the default left to right. */
254 | public HorizontalGroup reverse (boolean reverse) {
255 | this.reverse = reverse;
256 | return this;
257 | }
258 |
259 | public boolean getReverse () {
260 | return reverse;
261 | }
262 |
263 | /** Sets the space between children. */
264 | public HorizontalGroup space (float spacing) {
265 | this.spacing = spacing;
266 | return this;
267 | }
268 |
269 | public float getSpace () {
270 | return spacing;
271 | }
272 |
273 | /** Sets the padTop, padLeft, padBottom, and padRight to the specified value. */
274 | public HorizontalGroup pad (float pad) {
275 | padTop = pad;
276 | padLeft = pad;
277 | padBottom = pad;
278 | padRight = pad;
279 | return this;
280 | }
281 |
282 | public HorizontalGroup pad (float top, float left, float bottom, float right) {
283 | padTop = top;
284 | padLeft = left;
285 | padBottom = bottom;
286 | padRight = right;
287 | return this;
288 | }
289 |
290 | public HorizontalGroup padTop (float padTop) {
291 | this.padTop = padTop;
292 | return this;
293 | }
294 |
295 | public HorizontalGroup padLeft (float padLeft) {
296 | this.padLeft = padLeft;
297 | return this;
298 | }
299 |
300 | public HorizontalGroup padBottom (float padBottom) {
301 | this.padBottom = padBottom;
302 | return this;
303 | }
304 |
305 | public HorizontalGroup padRight (float padRight) {
306 | this.padRight = padRight;
307 | return this;
308 | }
309 |
310 | public float getPadTop () {
311 | return padTop;
312 | }
313 |
314 | public float getPadLeft () {
315 | return padLeft;
316 | }
317 |
318 | public float getPadBottom () {
319 | return padBottom;
320 | }
321 |
322 | public float getPadRight () {
323 | return padRight;
324 | }
325 |
326 | /** Sets the alignment of widgets within the horizontal group. Set to {@link com.badlogic.gdx.scenes.scene2d.utils.Align#center}, {@link com.badlogic.gdx.scenes.scene2d.utils.Align#top},
327 | * {@link com.badlogic.gdx.scenes.scene2d.utils.Align#bottom}, {@link com.badlogic.gdx.scenes.scene2d.utils.Align#left}, {@link com.badlogic.gdx.scenes.scene2d.utils.Align#right}, or any combination of those. */
328 | public HorizontalGroup align (int align) {
329 | this.align = align;
330 | return this;
331 | }
332 |
333 | /** Sets the alignment of widgets within the horizontal group to {@link com.badlogic.gdx.scenes.scene2d.utils.Align#center}. This clears any other alignment. */
334 | public HorizontalGroup center () {
335 | align = Align.center;
336 | return this;
337 | }
338 |
339 | /** Sets {@link com.badlogic.gdx.scenes.scene2d.utils.Align#top} and clears {@link com.badlogic.gdx.scenes.scene2d.utils.Align#bottom} for the alignment of widgets within the horizontal group. */
340 | public HorizontalGroup top () {
341 | align |= Align.top;
342 | align &= ~Align.bottom;
343 | return this;
344 | }
345 |
346 | /** Sets {@link com.badlogic.gdx.scenes.scene2d.utils.Align#bottom} and clears {@link com.badlogic.gdx.scenes.scene2d.utils.Align#top} for the alignment of widgets within the horizontal group. */
347 | public HorizontalGroup bottom () {
348 | align |= Align.bottom;
349 | align &= ~Align.top;
350 | return this;
351 | }
352 |
353 | public int getAlign () {
354 | return align;
355 | }
356 |
357 | public HorizontalGroup fill () {
358 | fill = 1f;
359 | return this;
360 | }
361 |
362 | /** @param fill 0 will use pref width. */
363 | public HorizontalGroup fill (float fill) {
364 | this.fill = fill;
365 | return this;
366 | }
367 |
368 | public float getFill () {
369 | return fill;
370 | }
371 | }
372 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/ui/ScrollPane.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.meizu.taskmanager.ui;
18 |
19 | import com.badlogic.gdx.Gdx;
20 | import com.badlogic.gdx.graphics.Color;
21 | import com.badlogic.gdx.graphics.g2d.Batch;
22 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
23 | import com.badlogic.gdx.math.Interpolation;
24 | import com.badlogic.gdx.math.MathUtils;
25 | import com.badlogic.gdx.math.Rectangle;
26 | import com.badlogic.gdx.math.Vector2;
27 | import com.badlogic.gdx.scenes.scene2d.Actor;
28 | import com.badlogic.gdx.scenes.scene2d.Event;
29 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
30 | import com.badlogic.gdx.scenes.scene2d.InputListener;
31 | import com.badlogic.gdx.scenes.scene2d.Stage;
32 | import com.badlogic.gdx.scenes.scene2d.ui.Skin;
33 | import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
34 | import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
35 | import com.badlogic.gdx.scenes.scene2d.utils.Cullable;
36 | import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
37 | import com.badlogic.gdx.scenes.scene2d.utils.Layout;
38 | import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
39 |
40 | /** A group that scrolls a child widget using scrollbars and/or mouse or touch dragging.
41 | *
42 | * The widget is sized to its preferred size. If the widget's preferred width or height is less than the size of this scroll pane,
43 | * it is set to the size of this scroll pane. Scrollbars appear when the widget is larger than the scroll pane.
44 | *
45 | * The scroll pane's preferred size is that of the child widget. At this size, the child widget will not need to scroll, so the
46 | * scroll pane is typically sized by ignoring the preferred size in one or both directions.
47 | * @author mzechner
48 | * @author Nathan Sweet */
49 | public class ScrollPane extends WidgetGroup {
50 | private ScrollPaneStyle style;
51 | private Actor widget;
52 |
53 | final Rectangle hScrollBounds = new Rectangle();
54 | final Rectangle vScrollBounds = new Rectangle();
55 | final Rectangle hKnobBounds = new Rectangle();
56 | final Rectangle vKnobBounds = new Rectangle();
57 | private final Rectangle widgetAreaBounds = new Rectangle();
58 | private final Rectangle widgetCullingArea = new Rectangle();
59 | private final Rectangle scissorBounds = new Rectangle();
60 | private ActorGestureListener flickScrollListener;
61 |
62 | boolean scrollX, scrollY;
63 | boolean vScrollOnRight = true;
64 | boolean hScrollOnBottom = true;
65 | float amountX, amountY;
66 | float visualAmountX, visualAmountY;
67 | float maxX, maxY;
68 | boolean touchScrollH, touchScrollV;
69 | final Vector2 lastPoint = new Vector2();
70 | float areaWidth, areaHeight;
71 | private boolean fadeScrollBars = true, smoothScrolling = true;
72 | float fadeAlpha, fadeAlphaSeconds = 1, fadeDelay, fadeDelaySeconds = 1;
73 | boolean cancelTouchFocus = true;
74 |
75 | boolean flickScroll = true;
76 | float velocityX, velocityY;
77 | float flingTimer;
78 | private boolean overscrollX = true, overscrollY = true;
79 | float flingTime = 0.5f;
80 | private float overscrollDistance = 50, overscrollSpeedMin = 30, overscrollSpeedMax = 200;
81 | private boolean forceScrollX, forceScrollY;
82 | private boolean disableX, disableY;
83 | private boolean clamp = true;
84 | private boolean scrollbarsOnTop;
85 | private boolean variableSizeKnobs = true;
86 | int draggingPointer = -1;
87 |
88 | /** @param widget May be null. */
89 | public ScrollPane (Actor widget) {
90 | this(widget, new ScrollPaneStyle());
91 | }
92 |
93 | /** @param widget May be null. */
94 | public ScrollPane (Actor widget, Skin skin) {
95 | this(widget, skin.get(ScrollPaneStyle.class));
96 | }
97 |
98 | /** @param widget May be null. */
99 | public ScrollPane (Actor widget, Skin skin, String styleName) {
100 | this(widget, skin.get(styleName, ScrollPaneStyle.class));
101 | }
102 |
103 | /** @param widget May be null. */
104 | public ScrollPane (Actor widget, ScrollPaneStyle style) {
105 | if (style == null) throw new IllegalArgumentException("style cannot be null.");
106 | this.style = style;
107 | setWidget(widget);
108 | setSize(150, 150);
109 |
110 | addCaptureListener(new InputListener() {
111 | private float handlePosition;
112 |
113 | public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
114 | if (draggingPointer != -1) return false;
115 | if (pointer == 0 && button != 0) return false;
116 | getStage().setScrollFocus(ScrollPane.this);
117 |
118 | if (!flickScroll) resetFade();
119 |
120 | if (fadeAlpha == 0) return false;
121 |
122 | if (scrollX && hScrollBounds.contains(x, y)) {
123 | event.stop();
124 | resetFade();
125 | if (hKnobBounds.contains(x, y)) {
126 | lastPoint.set(x, y);
127 | handlePosition = hKnobBounds.x;
128 | touchScrollH = true;
129 | draggingPointer = pointer;
130 | return true;
131 | }
132 | setScrollX(amountX + areaWidth * (x < hKnobBounds.x ? -1 : 1));
133 | return true;
134 | }
135 | if (scrollY && vScrollBounds.contains(x, y)) {
136 | event.stop();
137 | resetFade();
138 | if (vKnobBounds.contains(x, y)) {
139 | lastPoint.set(x, y);
140 | handlePosition = vKnobBounds.y;
141 | touchScrollV = true;
142 | draggingPointer = pointer;
143 | return true;
144 | }
145 | setScrollY(amountY + areaHeight * (y < vKnobBounds.y ? 1 : -1));
146 | return true;
147 | }
148 | return false;
149 | }
150 |
151 | public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
152 | if (pointer != draggingPointer) return;
153 | cancel();
154 | }
155 |
156 | public void touchDragged (InputEvent event, float x, float y, int pointer) {
157 | if (pointer != draggingPointer) return;
158 | if (touchScrollH) {
159 | float delta = x - lastPoint.x;
160 | float scrollH = handlePosition + delta;
161 | handlePosition = scrollH;
162 | scrollH = Math.max(hScrollBounds.x, scrollH);
163 | scrollH = Math.min(hScrollBounds.x + hScrollBounds.width - hKnobBounds.width, scrollH);
164 | float total = hScrollBounds.width - hKnobBounds.width;
165 | if (total != 0) setScrollPercentX((scrollH - hScrollBounds.x) / total);
166 | lastPoint.set(x, y);
167 | } else if (touchScrollV) {
168 | float delta = y - lastPoint.y;
169 | float scrollV = handlePosition + delta;
170 | handlePosition = scrollV;
171 | scrollV = Math.max(vScrollBounds.y, scrollV);
172 | scrollV = Math.min(vScrollBounds.y + vScrollBounds.height - vKnobBounds.height, scrollV);
173 | float total = vScrollBounds.height - vKnobBounds.height;
174 | if (total != 0) setScrollPercentY(1 - ((scrollV - vScrollBounds.y) / total));
175 | lastPoint.set(x, y);
176 | }
177 | }
178 |
179 | public boolean mouseMoved (InputEvent event, float x, float y) {
180 | if (!flickScroll) resetFade();
181 | return false;
182 | }
183 | });
184 |
185 | flickScrollListener = new ActorGestureListener() {
186 | boolean canMove;
187 | public void pan (InputEvent event, float x, float y, float deltaX, float deltaY) {
188 | if (!canMove && (forceScrollX || forceScrollY)) {
189 | if (forceScrollX) {
190 | if (Math.abs(deltaX) > Math.abs(deltaY)) {
191 | canMove = true;
192 | } else {
193 | return;
194 | }
195 | } else {
196 | if (Math.abs(deltaX) < Math.abs(deltaY)) {
197 | canMove = true;
198 | } else {
199 | return;
200 | }
201 | }
202 | }
203 | resetFade();
204 | amountX -= deltaX;
205 | amountY += deltaY;
206 | clamp();
207 | cancelTouchFocusedChild(event);
208 | }
209 |
210 | public void fling (InputEvent event, float x, float y, int button) {
211 | if (Math.abs(x) > 150) {
212 | flingTimer = flingTime;
213 | velocityX = x;
214 | cancelTouchFocusedChild(event);
215 | }
216 | if (Math.abs(y) > 150) {
217 | flingTimer = flingTime;
218 | velocityY = -y;
219 | cancelTouchFocusedChild(event);
220 | }
221 | }
222 |
223 | public boolean handle (Event event) {
224 | if (super.handle(event)) {
225 | if (((InputEvent)event).getType() == InputEvent.Type.touchDown) {
226 | flingTimer = 0;
227 | canMove=false;
228 | }
229 | return true;
230 | }
231 | return false;
232 | }
233 | };
234 | addListener(flickScrollListener);
235 |
236 | addListener(new InputListener() {
237 | public boolean scrolled (InputEvent event, float x, float y, int amount) {
238 | resetFade();
239 | if (scrollY)
240 | setScrollY(amountY + getMouseWheelY() * amount);
241 | else if (scrollX) //
242 | setScrollX(amountX + getMouseWheelX() * amount);
243 | else
244 | return false;
245 | return true;
246 | }
247 | });
248 | }
249 |
250 | void resetFade () {
251 | fadeAlpha = fadeAlphaSeconds;
252 | fadeDelay = fadeDelaySeconds;
253 | }
254 |
255 | void cancelTouchFocusedChild (InputEvent event) {
256 | if (!cancelTouchFocus) return;
257 | Stage stage = getStage();
258 | if (stage != null) stage.cancelTouchFocusExcept(flickScrollListener, this);
259 | }
260 |
261 | /** If currently scrolling by tracking a touch down, stop scrolling. */
262 | public void cancel () {
263 | draggingPointer = -1;
264 | touchScrollH = false;
265 | touchScrollV = false;
266 | flickScrollListener.getGestureDetector().cancel();
267 | }
268 |
269 | void clamp () {
270 | if (!clamp) return;
271 | scrollX(overscrollX ? MathUtils.clamp(amountX, -overscrollDistance, maxX + overscrollDistance) : MathUtils.clamp(amountX,
272 | 0, maxX));
273 | scrollY(overscrollY ? MathUtils.clamp(amountY, -overscrollDistance, maxY + overscrollDistance) : MathUtils.clamp(amountY,
274 | 0, maxY));
275 | }
276 |
277 | public void setStyle (ScrollPaneStyle style) {
278 | if (style == null) throw new IllegalArgumentException("style cannot be null.");
279 | this.style = style;
280 | invalidateHierarchy();
281 | }
282 |
283 | /** Returns the scroll pane's style. Modifying the returned style may not have an effect until
284 | * {@link #setStyle(ScrollPane.ScrollPaneStyle)} is called. */
285 | public ScrollPaneStyle getStyle () {
286 | return style;
287 | }
288 |
289 | public void act (float delta) {
290 | super.act(delta);
291 |
292 | boolean panning = flickScrollListener.getGestureDetector().isPanning();
293 | boolean animating = false;
294 |
295 | if (fadeAlpha > 0 && fadeScrollBars && !panning && !touchScrollH && !touchScrollV) {
296 | fadeDelay -= delta;
297 | if (fadeDelay <= 0) fadeAlpha = Math.max(0, fadeAlpha - delta);
298 | animating = true;
299 | }
300 |
301 | if (flingTimer > 0) {
302 | resetFade();
303 |
304 | float alpha = flingTimer / flingTime;
305 | amountX -= velocityX * alpha * delta;
306 | amountY -= velocityY * alpha * delta;
307 | clamp();
308 |
309 | // Stop fling if hit overscroll distance.
310 | if (amountX == -overscrollDistance) velocityX = 0;
311 | if (amountX >= maxX + overscrollDistance) velocityX = 0;
312 | if (amountY == -overscrollDistance) velocityY = 0;
313 | if (amountY >= maxY + overscrollDistance) velocityY = 0;
314 |
315 | flingTimer -= delta;
316 | if (flingTimer <= 0) {
317 | velocityX = 0;
318 | velocityY = 0;
319 | }
320 |
321 | animating = true;
322 | }
323 |
324 | if (smoothScrolling && flingTimer <= 0 && !touchScrollH && !touchScrollV && !panning) {
325 | if (visualAmountX != amountX) {
326 | if (visualAmountX < amountX)
327 | visualScrollX(Math.min(amountX, visualAmountX + Math.max(200 * delta, (amountX - visualAmountX) * 7 * delta)));
328 | else
329 | visualScrollX(Math.max(amountX, visualAmountX - Math.max(200 * delta, (visualAmountX - amountX) * 7 * delta)));
330 | animating = true;
331 | }
332 | if (visualAmountY != amountY) {
333 | if (visualAmountY < amountY)
334 | visualScrollY(Math.min(amountY, visualAmountY + Math.max(200 * delta, (amountY - visualAmountY) * 7 * delta)));
335 | else
336 | visualScrollY(Math.max(amountY, visualAmountY - Math.max(200 * delta, (visualAmountY - amountY) * 7 * delta)));
337 | animating = true;
338 | }
339 | } else {
340 | if (visualAmountX != amountX) visualScrollX(amountX);
341 | if (visualAmountY != amountY) visualScrollY(amountY);
342 | }
343 |
344 | if (!panning) {
345 | if (overscrollX && scrollX) {
346 | if (amountX < 0) {
347 | resetFade();
348 | amountX += (overscrollSpeedMin + (overscrollSpeedMax - overscrollSpeedMin) * -amountX / overscrollDistance)
349 | * delta;
350 | if (amountX > 0) scrollX(0);
351 | animating = true;
352 | } else if (amountX > maxX) {
353 | resetFade();
354 | amountX -= (overscrollSpeedMin + (overscrollSpeedMax - overscrollSpeedMin) * -(maxX - amountX)
355 | / overscrollDistance)
356 | * delta;
357 | if (amountX < maxX) scrollX(maxX);
358 | animating = true;
359 | }
360 | }
361 | if (overscrollY && scrollY) {
362 | if (amountY < 0) {
363 | resetFade();
364 | amountY += (overscrollSpeedMin + (overscrollSpeedMax - overscrollSpeedMin) * -amountY / overscrollDistance)
365 | * delta;
366 | if (amountY > 0) scrollY(0);
367 | animating = true;
368 | } else if (amountY > maxY) {
369 | resetFade();
370 | amountY -= (overscrollSpeedMin + (overscrollSpeedMax - overscrollSpeedMin) * -(maxY - amountY)
371 | / overscrollDistance)
372 | * delta;
373 | if (amountY < maxY) scrollY(maxY);
374 | animating = true;
375 | }
376 | }
377 | }
378 |
379 | if (animating) {
380 | Stage stage = getStage();
381 | if (stage != null && stage.getActionsRequestRendering()) Gdx.graphics.requestRendering();
382 | }
383 | }
384 |
385 | public void layout () {
386 | final Drawable bg = style.background;
387 | final Drawable hScrollKnob = style.hScrollKnob;
388 | final Drawable vScrollKnob = style.vScrollKnob;
389 |
390 | float bgLeftWidth = 0, bgRightWidth = 0, bgTopHeight = 0, bgBottomHeight = 0;
391 | if (bg != null) {
392 | bgLeftWidth = bg.getLeftWidth();
393 | bgRightWidth = bg.getRightWidth();
394 | bgTopHeight = bg.getTopHeight();
395 | bgBottomHeight = bg.getBottomHeight();
396 | }
397 |
398 | float width = getWidth();
399 | float height = getHeight();
400 |
401 | float scrollbarHeight = 0;
402 | if (hScrollKnob != null) scrollbarHeight = hScrollKnob.getMinHeight();
403 | if (style.hScroll != null) scrollbarHeight = Math.max(scrollbarHeight, style.hScroll.getMinHeight());
404 | float scrollbarWidth = 0;
405 | if (vScrollKnob != null) scrollbarWidth = vScrollKnob.getMinWidth();
406 | if (style.vScroll != null) scrollbarWidth = Math.max(scrollbarWidth, style.vScroll.getMinWidth());
407 |
408 | // Get available space size by subtracting background's padded area.
409 | areaWidth = width - bgLeftWidth - bgRightWidth;
410 | areaHeight = height - bgTopHeight - bgBottomHeight;
411 |
412 | if (widget == null) return;
413 |
414 | // Get widget's desired width.
415 | float widgetWidth, widgetHeight;
416 | if (widget instanceof Layout) {
417 | Layout layout = (Layout)widget;
418 | widgetWidth = layout.getPrefWidth();
419 | widgetHeight = layout.getPrefHeight();
420 | } else {
421 | widgetWidth = widget.getWidth();
422 | widgetHeight = widget.getHeight();
423 | }
424 |
425 | // Determine if horizontal/vertical scrollbars are needed.
426 | scrollX = forceScrollX || (widgetWidth > areaWidth && !disableX);
427 | scrollY = forceScrollY || (widgetHeight > areaHeight && !disableY);
428 |
429 | boolean fade = fadeScrollBars;
430 | if (!fade) {
431 | // Check again, now taking into account the area that's taken up by any enabled scrollbars.
432 | if (scrollY) {
433 | areaWidth -= scrollbarWidth;
434 | if (!scrollX && widgetWidth > areaWidth && !disableX) scrollX = true;
435 | }
436 | if (scrollX) {
437 | areaHeight -= scrollbarHeight;
438 | if (!scrollY && widgetHeight > areaHeight && !disableY) {
439 | scrollY = true;
440 | areaWidth -= scrollbarWidth;
441 | }
442 | }
443 | }
444 |
445 | // The bounds of the scrollable area for the widget.
446 | widgetAreaBounds.set(bgLeftWidth, bgBottomHeight, areaWidth, areaHeight);
447 |
448 | if (fade) {
449 | // Make sure widget is drawn under fading scrollbars.
450 | if (scrollX && scrollY) {
451 | areaHeight -= scrollbarHeight;
452 | areaWidth -= scrollbarWidth;
453 | }
454 | } else {
455 | if (scrollbarsOnTop) {
456 | // Make sure widget is drawn under non-fading scrollbars.
457 | if (scrollX) widgetAreaBounds.height += scrollbarHeight;
458 | if (scrollY) widgetAreaBounds.width += scrollbarWidth;
459 | } else {
460 | // Offset widget area y for horizontal scrollbar at bottom.
461 | if (scrollX && hScrollOnBottom) widgetAreaBounds.y += scrollbarHeight;
462 | // Offset widget area x for vertical scrollbar at left.
463 | if (scrollY && !vScrollOnRight) widgetAreaBounds.x += scrollbarWidth;
464 | }
465 | }
466 |
467 | // If the widget is smaller than the available space, make it take up the available space.
468 | widgetWidth = disableX ? areaWidth : Math.max(areaWidth, widgetWidth);
469 | widgetHeight = disableY ? areaHeight : Math.max(areaHeight, widgetHeight);
470 |
471 | maxX = widgetWidth - areaWidth;
472 | maxY = widgetHeight - areaHeight;
473 | if (fade) {
474 | // Make sure widget is drawn under fading scrollbars.
475 | if (scrollX) maxY -= scrollbarHeight;
476 | if (scrollY) maxX -= scrollbarWidth;
477 | }
478 | scrollX(MathUtils.clamp(amountX, 0, maxX));
479 | scrollY(MathUtils.clamp(amountY, 0, maxY));
480 |
481 | // Set the bounds and scroll knob sizes if scrollbars are needed.
482 | if (scrollX) {
483 | if (hScrollKnob != null) {
484 | float hScrollHeight = style.hScroll != null ? style.hScroll.getMinHeight() : hScrollKnob.getMinHeight();
485 | // The corner gap where the two scroll bars intersect might have to flip from right to left.
486 | float boundsX = vScrollOnRight ? bgLeftWidth : bgLeftWidth + scrollbarWidth;
487 | // Scrollbar on the top or bottom.
488 | float boundsY = hScrollOnBottom ? bgBottomHeight : height - bgTopHeight - hScrollHeight;
489 | hScrollBounds.set(boundsX, boundsY, areaWidth, hScrollHeight);
490 | if (variableSizeKnobs)
491 | hKnobBounds.width = Math.max(hScrollKnob.getMinWidth(), (int)(hScrollBounds.width * areaWidth / widgetWidth));
492 | else
493 | hKnobBounds.width = hScrollKnob.getMinWidth();
494 |
495 | hKnobBounds.height = hScrollKnob.getMinHeight();
496 |
497 | hKnobBounds.x = hScrollBounds.x + (int)((hScrollBounds.width - hKnobBounds.width) * getScrollPercentX());
498 | hKnobBounds.y = hScrollBounds.y;
499 | } else {
500 | hScrollBounds.set(0, 0, 0, 0);
501 | hKnobBounds.set(0, 0, 0, 0);
502 | }
503 | }
504 | if (scrollY) {
505 | if (vScrollKnob != null) {
506 | float vScrollWidth = style.vScroll != null ? style.vScroll.getMinWidth() : vScrollKnob.getMinWidth();
507 | // the small gap where the two scroll bars intersect might have to flip from bottom to top
508 | float boundsX, boundsY;
509 | if (hScrollOnBottom) {
510 | boundsY = height - bgTopHeight - areaHeight;
511 | } else {
512 | boundsY = bgBottomHeight;
513 | }
514 | // bar on the left or right
515 | if (vScrollOnRight) {
516 | boundsX = width - bgRightWidth - vScrollWidth;
517 | } else {
518 | boundsX = bgLeftWidth;
519 | }
520 | vScrollBounds.set(boundsX, boundsY, vScrollWidth, areaHeight);
521 | vKnobBounds.width = vScrollKnob.getMinWidth();
522 | if (variableSizeKnobs)
523 | vKnobBounds.height = Math.max(vScrollKnob.getMinHeight(), (int)(vScrollBounds.height * areaHeight / widgetHeight));
524 | else
525 | vKnobBounds.height = vScrollKnob.getMinHeight();
526 |
527 | if (vScrollOnRight) {
528 | vKnobBounds.x = width - bgRightWidth - vScrollKnob.getMinWidth();
529 | } else {
530 | vKnobBounds.x = bgLeftWidth;
531 | }
532 | vKnobBounds.y = vScrollBounds.y + (int)((vScrollBounds.height - vKnobBounds.height) * (1 - getScrollPercentY()));
533 | } else {
534 | vScrollBounds.set(0, 0, 0, 0);
535 | vKnobBounds.set(0, 0, 0, 0);
536 | }
537 | }
538 |
539 | widget.setSize(widgetWidth, widgetHeight);
540 | if (widget instanceof Layout) ((Layout)widget).validate();
541 | }
542 |
543 | @Override
544 | public void draw (Batch batch, float parentAlpha) {
545 | if (widget == null) return;
546 |
547 | validate();
548 |
549 | // Setup transform for this group.
550 | applyTransform(batch, computeTransform());
551 |
552 | if (scrollX)
553 | hKnobBounds.x = hScrollBounds.x + (int)((hScrollBounds.width - hKnobBounds.width) * getVisualScrollPercentX());
554 | if (scrollY)
555 | vKnobBounds.y = vScrollBounds.y + (int)((vScrollBounds.height - vKnobBounds.height) * (1 - getVisualScrollPercentY()));
556 |
557 | // Calculate the widget's position depending on the scroll state and available widget area.
558 | float y = widgetAreaBounds.y;
559 | if (!scrollY)
560 | y -= (int)maxY;
561 | else
562 | y -= (int)(maxY - visualAmountY);
563 |
564 | float x = widgetAreaBounds.x;
565 | if (scrollX) x -= (int)visualAmountX;
566 |
567 | if (!fadeScrollBars && scrollbarsOnTop) {
568 | if (scrollX && hScrollOnBottom) {
569 | float scrollbarHeight = 0;
570 | if (style.hScrollKnob != null) scrollbarHeight = style.hScrollKnob.getMinHeight();
571 | if (style.hScroll != null) scrollbarHeight = Math.max(scrollbarHeight, style.hScroll.getMinHeight());
572 | y += scrollbarHeight;
573 | }
574 | if (scrollY && !vScrollOnRight) {
575 | float scrollbarWidth = 0;
576 | if (style.hScrollKnob != null) scrollbarWidth = style.hScrollKnob.getMinWidth();
577 | if (style.hScroll != null) scrollbarWidth = Math.max(scrollbarWidth, style.hScroll.getMinWidth());
578 | x += scrollbarWidth;
579 | }
580 | }
581 |
582 | widget.setPosition(x, y);
583 |
584 | if (widget instanceof Cullable) {
585 | widgetCullingArea.x = -widget.getX() + widgetAreaBounds.x;
586 | widgetCullingArea.y = -widget.getY() + widgetAreaBounds.y;
587 | widgetCullingArea.width = widgetAreaBounds.width;
588 | widgetCullingArea.height = widgetAreaBounds.height;
589 | ((Cullable)widget).setCullingArea(widgetCullingArea);
590 | }
591 |
592 | // Draw the background ninepatch.
593 | Color color = getColor();
594 | batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
595 | if (style.background != null) {
596 | style.background.draw(batch, 0, 0, getWidth(), getHeight());
597 | batch.flush();
598 | }
599 |
600 | // Caculate the scissor bounds based on the batch transform, the available widget area and the camera transform. We need to
601 | // project those to screen coordinates for OpenGL ES to consume.
602 | getStage().calculateScissors(widgetAreaBounds, scissorBounds);
603 |
604 | // Enable scissors for widget area and draw the widget.
605 | if (ScissorStack.pushScissors(scissorBounds)) {
606 | drawChildren(batch, parentAlpha);
607 | batch.flush();
608 | ScissorStack.popScissors();
609 | }
610 |
611 | // Render scrollbars and knobs on top.
612 | batch.setColor(color.r, color.g, color.b, color.a * parentAlpha * Interpolation.fade.apply(fadeAlpha / fadeAlphaSeconds));
613 | if (scrollX && scrollY) {
614 | if (style.corner != null) {
615 | style.corner
616 | .draw(batch, hScrollBounds.x + hScrollBounds.width, hScrollBounds.y, vScrollBounds.width, vScrollBounds.y);
617 | }
618 | }
619 | if (scrollX) {
620 | if (style.hScroll != null)
621 | style.hScroll.draw(batch, hScrollBounds.x, hScrollBounds.y, hScrollBounds.width, hScrollBounds.height);
622 | if (style.hScrollKnob != null)
623 | style.hScrollKnob.draw(batch, hKnobBounds.x, hKnobBounds.y, hKnobBounds.width, hKnobBounds.height);
624 | }
625 | if (scrollY) {
626 | if (style.vScroll != null)
627 | style.vScroll.draw(batch, vScrollBounds.x, vScrollBounds.y, vScrollBounds.width, vScrollBounds.height);
628 | if (style.vScrollKnob != null)
629 | style.vScrollKnob.draw(batch, vKnobBounds.x, vKnobBounds.y, vKnobBounds.width, vKnobBounds.height);
630 | }
631 |
632 | resetTransform(batch);
633 | }
634 |
635 | /** Generate fling gesture.
636 | * @param flingTime Time in seconds for which you want to fling last.
637 | * @param velocityX Velocity for horizontal direction.
638 | * @param velocityY Velocity for vertical direction. */
639 | public void fling (float flingTime, float velocityX, float velocityY) {
640 | this.flingTimer = flingTime;
641 | this.velocityX = velocityX;
642 | this.velocityY = velocityY;
643 | }
644 |
645 | public float getPrefWidth () {
646 | if (widget instanceof Layout) {
647 | float width = ((Layout)widget).getPrefWidth();
648 | if (style.background != null) width += style.background.getLeftWidth() + style.background.getRightWidth();
649 | if (forceScrollY) {
650 | float scrollbarWidth = 0;
651 | if (style.vScrollKnob != null) scrollbarWidth = style.vScrollKnob.getMinWidth();
652 | if (style.vScroll != null) scrollbarWidth = Math.max(scrollbarWidth, style.vScroll.getMinWidth());
653 | width += scrollbarWidth;
654 | }
655 | return width;
656 | }
657 | return 150;
658 | }
659 |
660 | public float getPrefHeight () {
661 | if (widget instanceof Layout) {
662 | float height = ((Layout)widget).getPrefHeight();
663 | if (style.background != null) height += style.background.getTopHeight() + style.background.getBottomHeight();
664 | if (forceScrollX) {
665 | float scrollbarHeight = 0;
666 | if (style.hScrollKnob != null) scrollbarHeight = style.hScrollKnob.getMinHeight();
667 | if (style.hScroll != null) scrollbarHeight = Math.max(scrollbarHeight, style.hScroll.getMinHeight());
668 | height += scrollbarHeight;
669 | }
670 | return height;
671 | }
672 | return 150;
673 | }
674 |
675 | public float getMinWidth () {
676 | return 0;
677 | }
678 |
679 | public float getMinHeight () {
680 | return 0;
681 | }
682 |
683 | /** Sets the {@link com.badlogic.gdx.scenes.scene2d.Actor} embedded in this scroll pane.
684 | * @param widget May be null to remove any current actor. */
685 | public void setWidget (Actor widget) {
686 | if (widget == this) throw new IllegalArgumentException("widget cannot be the ScrollPane.");
687 | if (this.widget != null) super.removeActor(this.widget);
688 | this.widget = widget;
689 | if (widget != null) super.addActor(widget);
690 | }
691 |
692 | /** Returns the actor embedded in this scroll pane, or null. */
693 | public Actor getWidget () {
694 | return widget;
695 | }
696 |
697 | /** @deprecated ScrollPane may have only a single child.
698 | * @see #setWidget(com.badlogic.gdx.scenes.scene2d.Actor) */
699 | public void addActor (Actor actor) {
700 | throw new UnsupportedOperationException("Use ScrollPane#setWidget.");
701 | }
702 |
703 | /** @deprecated ScrollPane may have only a single child.
704 | * @see #setWidget(com.badlogic.gdx.scenes.scene2d.Actor) */
705 | public void addActorAt (int index, Actor actor) {
706 | throw new UnsupportedOperationException("Use ScrollPane#setWidget.");
707 | }
708 |
709 | /** @deprecated ScrollPane may have only a single child.
710 | * @see #setWidget(com.badlogic.gdx.scenes.scene2d.Actor) */
711 | public void addActorBefore (Actor actorBefore, Actor actor) {
712 | throw new UnsupportedOperationException("Use ScrollPane#setWidget.");
713 | }
714 |
715 | /** @deprecated ScrollPane may have only a single child.
716 | * @see #setWidget(com.badlogic.gdx.scenes.scene2d.Actor) */
717 | public void addActorAfter (Actor actorAfter, Actor actor) {
718 | throw new UnsupportedOperationException("Use ScrollPane#setWidget.");
719 | }
720 |
721 | public boolean removeActor (Actor actor) {
722 | if (actor != widget) return false;
723 | setWidget(null);
724 | return true;
725 | }
726 |
727 | public Actor hit (float x, float y, boolean touchable) {
728 | if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) return null;
729 | if (scrollX && hScrollBounds.contains(x, y)) return this;
730 | if (scrollY && vScrollBounds.contains(x, y)) return this;
731 | return super.hit(x, y, touchable);
732 | }
733 |
734 | /** Called whenever the x scroll amount is changed. */
735 | protected void scrollX (float pixelsX) {
736 | this.amountX = pixelsX;
737 | }
738 |
739 | /** Called whenever the y scroll amount is changed. */
740 | protected void scrollY (float pixelsY) {
741 | this.amountY = pixelsY;
742 | }
743 |
744 | /** Called whenever the visual x scroll amount is changed. */
745 | protected void visualScrollX (float pixelsX) {
746 | this.visualAmountX = pixelsX;
747 | }
748 |
749 | /** Called whenever the visual y scroll amount is changed. */
750 | protected void visualScrollY (float pixelsY) {
751 | this.visualAmountY = pixelsY;
752 | }
753 |
754 | /** Returns the amount to scroll horizontally when the mouse wheel is scrolled. */
755 | protected float getMouseWheelX () {
756 | return Math.max(areaWidth * 0.9f, maxX * 0.1f) / 4;
757 | }
758 |
759 | /** Returns the amount to scroll vertically when the mouse wheel is scrolled. */
760 | protected float getMouseWheelY () {
761 | return Math.max(areaHeight * 0.9f, maxY * 0.1f) / 4;
762 | }
763 |
764 | public void setScrollX (float pixels) {
765 | scrollX(MathUtils.clamp(pixels, 0, maxX));
766 | }
767 |
768 | /** Returns the x scroll position in pixels, where 0 is the left of the scroll pane. */
769 | public float getScrollX () {
770 | return amountX;
771 | }
772 |
773 | public void setScrollY (float pixels) {
774 | scrollY(MathUtils.clamp(pixels, 0, maxY));
775 | }
776 |
777 | /** Returns the y scroll position in pixels, where 0 is the top of the scroll pane. */
778 | public float getScrollY () {
779 | return amountY;
780 | }
781 |
782 | /** Sets the visual scroll amount equal to the scroll amount. This can be used when setting the scroll amount without animating. */
783 | public void updateVisualScroll () {
784 | visualAmountX = amountX;
785 | visualAmountY = amountY;
786 | }
787 |
788 | public float getVisualScrollX () {
789 | return !scrollX ? 0 : visualAmountX;
790 | }
791 |
792 | public float getVisualScrollY () {
793 | return !scrollY ? 0 : visualAmountY;
794 | }
795 |
796 | public float getVisualScrollPercentX () {
797 | return MathUtils.clamp(visualAmountX / maxX, 0, 1);
798 | }
799 |
800 | public float getVisualScrollPercentY () {
801 | return MathUtils.clamp(visualAmountY / maxY, 0, 1);
802 | }
803 |
804 | public float getScrollPercentX () {
805 | return MathUtils.clamp(amountX / maxX, 0, 1);
806 | }
807 |
808 | public void setScrollPercentX (float percentX) {
809 | scrollX(maxX * MathUtils.clamp(percentX, 0, 1));
810 | }
811 |
812 | public float getScrollPercentY () {
813 | return MathUtils.clamp(amountY / maxY, 0, 1);
814 | }
815 |
816 | public void setScrollPercentY (float percentY) {
817 | scrollY(maxY * MathUtils.clamp(percentY, 0, 1));
818 | }
819 |
820 | public void setFlickScroll (boolean flickScroll) {
821 | if (this.flickScroll == flickScroll) return;
822 | this.flickScroll = flickScroll;
823 | if (flickScroll)
824 | addListener(flickScrollListener);
825 | else
826 | removeListener(flickScrollListener);
827 | invalidate();
828 | }
829 |
830 | public void setFlickScrollTapSquareSize (float halfTapSquareSize) {
831 | flickScrollListener.getGestureDetector().setTapSquareSize(halfTapSquareSize);
832 | }
833 |
834 | /** Sets the scroll offset so the specified rectangle is fully in view, if possible. Coordinates are in the scroll pane widget's
835 | * coordinate system. */
836 | public void scrollTo (float x, float y, float width, float height) {
837 | scrollTo(x, y, width, height, false, false);
838 | }
839 |
840 | /** Sets the scroll offset so the specified rectangle is fully in view, and optionally centered vertically and/or horizontally,
841 | * if possible. Coordinates are in the scroll pane widget's coordinate system. */
842 | public void scrollTo (float x, float y, float width, float height, boolean centerHorizontal, boolean centerVertical) {
843 | float amountX = this.amountX;
844 | if (centerHorizontal) {
845 | amountX = x - areaWidth / 2 + width / 2;
846 | } else {
847 | if (x + width > amountX + areaWidth) amountX = x + width - areaWidth;
848 | if (x < amountX) amountX = x;
849 | }
850 | scrollX(MathUtils.clamp(amountX, 0, maxX));
851 |
852 | float amountY = this.amountY;
853 | if (centerVertical) {
854 | amountY = maxY - y + areaHeight / 2 - height / 2;
855 | } else {
856 | if (amountY > maxY - y - height + areaHeight) amountY = maxY - y - height + areaHeight;
857 | if (amountY < maxY - y) amountY = maxY - y;
858 | }
859 | scrollY(MathUtils.clamp(amountY, 0, maxY));
860 | }
861 |
862 | /** Returns the maximum scroll value in the x direction. */
863 | public float getMaxX () {
864 | return maxX;
865 | }
866 |
867 | /** Returns the maximum scroll value in the y direction. */
868 | public float getMaxY () {
869 | return maxY;
870 | }
871 |
872 | public float getScrollBarHeight () {
873 | if (!scrollX) return 0;
874 | float height = 0;
875 | if (style.hScrollKnob != null) height = style.hScrollKnob.getMinHeight();
876 | if (style.hScroll != null) height = Math.max(height, style.hScroll.getMinHeight());
877 | return height;
878 | }
879 |
880 | public float getScrollBarWidth () {
881 | if (!scrollY) return 0;
882 | float width = 0;
883 | if (style.vScrollKnob != null) width = style.vScrollKnob.getMinWidth();
884 | if (style.vScroll != null) width = Math.max(width, style.vScroll.getMinWidth());
885 | return width;
886 | }
887 |
888 | /** Returns the width of the scrolled viewport. */
889 | public float getScrollWidth () {
890 | return areaWidth;
891 | }
892 |
893 | /** Returns the height of the scrolled viewport. */
894 | public float getScrollHeight () {
895 | return areaHeight;
896 | }
897 |
898 | /** Returns true if the widget is larger than the scroll pane horizontally. */
899 | public boolean isScrollX () {
900 | return scrollX;
901 | }
902 |
903 | /** Returns true if the widget is larger than the scroll pane vertically. */
904 | public boolean isScrollY () {
905 | return scrollY;
906 | }
907 |
908 | /** Disables scrolling in a direction. The widget will be sized to the FlickScrollPane in the disabled direction. */
909 | public void setScrollingDisabled (boolean x, boolean y) {
910 | disableX = x;
911 | disableY = y;
912 | }
913 |
914 | public boolean isLeftEdge () {
915 | return !scrollX || amountX <= 0;
916 | }
917 |
918 | public boolean isRightEdge () {
919 | return !scrollX || amountX >= maxX;
920 | }
921 |
922 | public boolean isTopEdge () {
923 | return !scrollY || amountY <= 0;
924 | }
925 |
926 | public boolean isBottomEdge () {
927 | return !scrollY || amountY >= maxY;
928 | }
929 |
930 | public boolean isDragging () {
931 | return draggingPointer != -1;
932 | }
933 |
934 | public boolean isPanning () {
935 | return flickScrollListener.getGestureDetector().isPanning();
936 | }
937 |
938 | public boolean isFlinging () {
939 | return flingTimer > 0;
940 | }
941 |
942 | public void setVelocityX (float velocityX) {
943 | this.velocityX = velocityX;
944 | }
945 |
946 | /** Gets the flick scroll y velocity. */
947 | public float getVelocityX () {
948 | if (flingTimer <= 0) return 0;
949 | float alpha = flingTimer / flingTime;
950 | alpha = alpha * alpha * alpha;
951 | return velocityX * alpha * alpha * alpha;
952 | }
953 |
954 | public void setVelocityY (float velocityY) {
955 | this.velocityY = velocityY;
956 | }
957 |
958 | /** Gets the flick scroll y velocity. */
959 | public float getVelocityY () {
960 | return velocityY;
961 | }
962 |
963 | /** For flick scroll, if true the widget can be scrolled slightly past its bounds and will animate back to its bounds when
964 | * scrolling is stopped. Default is true. */
965 | public void setOverscroll (boolean overscrollX, boolean overscrollY) {
966 | this.overscrollX = overscrollX;
967 | this.overscrollY = overscrollY;
968 | }
969 |
970 | /** For flick scroll, sets the overscroll distance in pixels and the speed it returns to the widget's bounds in seconds. Default
971 | * is 50, 30, 200. */
972 | public void setupOverscroll (float distance, float speedMin, float speedMax) {
973 | overscrollDistance = distance;
974 | overscrollSpeedMin = speedMin;
975 | overscrollSpeedMax = speedMax;
976 | }
977 |
978 | /** Forces enabling scrollbars (for non-flick scroll) and overscrolling (for flick scroll) in a direction, even if the contents
979 | * do not exceed the bounds in that direction. */
980 | public void setForceScroll (boolean x, boolean y) {
981 | forceScrollX = x;
982 | forceScrollY = y;
983 | }
984 |
985 | public boolean isForceScrollX () {
986 | return forceScrollX;
987 | }
988 |
989 | public boolean isForceScrollY () {
990 | return forceScrollY;
991 | }
992 |
993 | /** For flick scroll, sets the amount of time in seconds that a fling will continue to scroll. Default is 1. */
994 | public void setFlingTime (float flingTime) {
995 | this.flingTime = flingTime;
996 | }
997 |
998 | /** For flick scroll, prevents scrolling out of the widget's bounds. Default is true. */
999 | public void setClamp (boolean clamp) {
1000 | this.clamp = clamp;
1001 | }
1002 |
1003 | /** Set the position of the vertical and horizontal scroll bars. */
1004 | public void setScrollBarPositions (boolean bottom, boolean right) {
1005 | hScrollOnBottom = bottom;
1006 | vScrollOnRight = right;
1007 | }
1008 |
1009 | /** When true the scrollbars don't reduce the scrollable size and fade out after some time of not being used. */
1010 | public void setFadeScrollBars (boolean fadeScrollBars) {
1011 | if (this.fadeScrollBars == fadeScrollBars) return;
1012 | this.fadeScrollBars = fadeScrollBars;
1013 | if (!fadeScrollBars) fadeAlpha = fadeAlphaSeconds;
1014 | invalidate();
1015 | }
1016 |
1017 | public void setupFadeScrollBars (float fadeAlphaSeconds, float fadeDelaySeconds) {
1018 | this.fadeAlphaSeconds = fadeAlphaSeconds;
1019 | this.fadeDelaySeconds = fadeDelaySeconds;
1020 | }
1021 |
1022 | public void setSmoothScrolling (boolean smoothScrolling) {
1023 | this.smoothScrolling = smoothScrolling;
1024 | }
1025 |
1026 | /** When false (the default), the widget is clipped so it is not drawn under the scrollbars. When true, the widget is clipped to
1027 | * the entire scroll pane bounds and the scrollbars are drawn on top of the widget. If {@link #setFadeScrollBars(boolean)} is
1028 | * true, the scroll bars are always drawn on top. */
1029 | public void setScrollbarsOnTop (boolean scrollbarsOnTop) {
1030 | this.scrollbarsOnTop = scrollbarsOnTop;
1031 | invalidate();
1032 | }
1033 |
1034 | public boolean getVariableSizeKnobs () {
1035 | return variableSizeKnobs;
1036 | }
1037 |
1038 | /** If true, the scroll knobs are sized based on {@link #getMaxX()} or {@link #getMaxY()}. If false, the scroll knobs are sized
1039 | * based on {@link com.badlogic.gdx.scenes.scene2d.utils.Drawable#getMinWidth()} or {@link com.badlogic.gdx.scenes.scene2d.utils.Drawable#getMinHeight()}. Default is true. */
1040 | public void setVariableSizeKnobs (boolean variableSizeKnobs) {
1041 | this.variableSizeKnobs = variableSizeKnobs;
1042 | }
1043 |
1044 | /** When true (default), the {@link com.badlogic.gdx.scenes.scene2d.Stage#cancelTouchFocus()} touch focus} is cancelled when flick scrolling begins. This causes
1045 | * widgets inside the scrollpane that have received touchDown to receive touchUp when flick scrolling begins. */
1046 | public void setCancelTouchFocus (boolean cancelTouchFocus) {
1047 | this.cancelTouchFocus = cancelTouchFocus;
1048 | }
1049 |
1050 | public void drawDebug (ShapeRenderer shapes) {
1051 | shapes.flush();
1052 | applyTransform(shapes, computeTransform());
1053 | if (ScissorStack.pushScissors(scissorBounds)) {
1054 | drawDebugChildren(shapes);
1055 | ScissorStack.popScissors();
1056 | }
1057 | resetTransform(shapes);
1058 | }
1059 |
1060 | public String toString () {
1061 | if (widget == null)
1062 | return super.toString();
1063 | else
1064 | return super.toString() + ": " + widget.toString();
1065 | }
1066 |
1067 | /** The style for a scroll pane, see {@link ScrollPane}.
1068 | * @author mzechner
1069 | * @author Nathan Sweet */
1070 | static public class ScrollPaneStyle {
1071 | /** Optional. */
1072 | public Drawable background, corner;
1073 | /** Optional. */
1074 | public Drawable hScroll, hScrollKnob;
1075 | /** Optional. */
1076 | public Drawable vScroll, vScrollKnob;
1077 |
1078 | public ScrollPaneStyle () {
1079 | }
1080 |
1081 | public ScrollPaneStyle (Drawable background, Drawable hScroll, Drawable hScrollKnob, Drawable vScroll, Drawable vScrollKnob) {
1082 | this.background = background;
1083 | this.hScroll = hScroll;
1084 | this.hScrollKnob = hScrollKnob;
1085 | this.vScroll = vScroll;
1086 | this.vScrollKnob = vScrollKnob;
1087 | }
1088 |
1089 | public ScrollPaneStyle (ScrollPaneStyle style) {
1090 | this.background = style.background;
1091 | this.hScroll = style.hScroll;
1092 | this.hScrollKnob = style.hScrollKnob;
1093 | this.vScroll = style.vScroll;
1094 | this.vScrollKnob = style.vScrollKnob;
1095 | }
1096 | }
1097 | }
1098 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/utils/action/CancelableAction.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.utils.action;
2 |
3 | public interface CancelableAction {
4 | public void cancel();
5 | }
6 |
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/utils/animation/FloatEvaluator.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.utils.animation;
2 |
3 | public class FloatEvaluator implements TypeEvaluator {
4 | public Float evaluate(float fraction, Number startValue, Number endValue) {
5 | float startFloat = startValue.floatValue();
6 | return startFloat + fraction * (endValue.floatValue() - startFloat);
7 | }
8 | }
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/utils/animation/IntEvaluator.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.utils.animation;
2 |
3 | public class IntEvaluator implements TypeEvaluator {
4 |
5 | public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
6 | int startInt = startValue;
7 | return (int)(startInt + fraction * (endValue - startInt));
8 | }
9 | }
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/utils/animation/TypeEvaluator.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.utils.animation;
2 |
3 | public interface TypeEvaluator {
4 | public T evaluate(float fraction, T startValue, T endValue);
5 |
6 | }
--------------------------------------------------------------------------------
/core/src/com/meizu/taskmanager/utils/eventbus/EventBusUtil.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.utils.eventbus;
2 |
3 | import com.google.common.eventbus.EventBus;
4 |
5 | public class EventBusUtil {
6 | protected static EventBus eventBus;
7 |
8 | public synchronized static EventBus getDefaultEventBus() {
9 | if (eventBus == null) {
10 | eventBus = new EventBus("taskmanager");
11 | }
12 | return eventBus;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/desktop/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 |
3 | sourceCompatibility = 1.7
4 | sourceSets.main.java.srcDirs = [ "src/" ]
5 |
6 | project.ext.mainClassName = "com.meizu.taskmanager.desktop.DesktopLauncher"
7 | project.ext.assetsDir = new File("../android/assets");
8 |
9 | task run(dependsOn: classes, type: JavaExec) {
10 | main = project.mainClassName
11 | classpath = sourceSets.main.runtimeClasspath
12 | standardInput = System.in
13 | workingDir = project.assetsDir
14 | ignoreExitValue = true
15 | }
16 |
17 | task runDesktop(dependsOn: classes, type: JavaExec) {
18 | main = project.mainClassName
19 | classpath = sourceSets.main.runtimeClasspath
20 | standardInput = System.in
21 | workingDir = project.assetsDir
22 | ignoreExitValue = true
23 | }
24 |
25 | task dist(type: Jar) {
26 | from files(sourceSets.main.output.classesDir)
27 | from files(sourceSets.main.output.resourcesDir)
28 | from {configurations.compile.collect {zipTree(it)}}
29 | from files(project.assetsDir);
30 |
31 | manifest {
32 | attributes 'Main-Class': project.mainClassName
33 | }
34 | }
35 |
36 | dist.dependsOn classes
37 |
38 | eclipse {
39 | project {
40 | name = appName + "-desktop"
41 | linkedResource name: 'assets', type: '2', location: 'PARENT-1-PROJECT_LOC/android/assets'
42 | }
43 | }
44 |
45 | task afterEclipseImport(description: "Post processing after project generation", group: "IDE") {
46 | doLast {
47 | def classpath = new XmlParser().parse(file(".classpath"))
48 | new Node(classpath, "classpathentry", [ kind: 'src', path: 'assets' ]);
49 | def writer = new FileWriter(file(".classpath"))
50 | def printer = new XmlNodePrinter(new PrintWriter(writer))
51 | printer.setPreserveWhitespace(true)
52 | printer.print(classpath)
53 | }
54 | }
--------------------------------------------------------------------------------
/desktop/src/com/meizu/taskmanager/desktop/DesktopLauncher.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.desktop;
2 |
3 | import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
4 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
5 | import com.meizu.taskmanager.TaskManager;
6 |
7 | public class DesktopLauncher {
8 | public static void main (String[] arg) {
9 | LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
10 | config.height=800;
11 | config.width=450;
12 | config.disableAudio = true;
13 | new LwjglApplication(new TaskManager(), config);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.daemon=true
2 | org.gradle.jvmargs=-Xms128m -Xmx512m
3 | org.gradle.configureondemand=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Sep 21 13:08:26 CEST 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/html/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 | apply plugin: "jetty"
3 |
4 | gwt {
5 | gwtVersion='2.6.0' // Should match the gwt version used for building the gwt backend
6 | maxHeapSize="1G" // Default 256m is not enough for gwt compiler. GWT is HUNGRY
7 | minHeapSize="1G"
8 |
9 | src = files(file("src/")) // Needs to be in front of "modules" below.
10 | modules 'com.meizu.taskmanager.GdxDefinition'
11 | devModules 'com.meizu.taskmanager.GdxDefinitionSuperdev'
12 | project.webAppDirName = 'webapp'
13 |
14 | compiler {
15 | strict = true;
16 | enableClosureCompiler = true;
17 | disableCastChecking = true;
18 | }
19 | }
20 |
21 | task draftRun(type: JettyRunWar) {
22 | dependsOn draftWar
23 | dependsOn.remove('war')
24 | webApp=draftWar.archivePath
25 | daemon=true
26 | }
27 |
28 | task superDev(type: de.richsource.gradle.plugins.gwt.GwtSuperDev) {
29 | dependsOn draftRun
30 | doFirst {
31 | gwt.modules = gwt.devModules
32 | }
33 | }
34 |
35 | task dist(dependsOn: [clean, compileGwt]) {
36 | doLast {
37 | file("build/dist").mkdirs()
38 | copy {
39 | from "build/gwt/out"
40 | into "build/dist"
41 | }
42 | copy {
43 | from "webapp"
44 | into "build/dist"
45 | }
46 | copy {
47 | from "war"
48 | into "build/dist"
49 | }
50 | }
51 | }
52 |
53 | draftWar {
54 | from "war"
55 | }
56 |
57 | task addSource << {
58 | sourceSets.main.compileClasspath += files(project(':core').sourceSets.main.allJava.srcDirs)
59 | }
60 |
61 | tasks.compileGwt.dependsOn(addSource)
62 | tasks.draftCompileGwt.dependsOn(addSource)
63 |
64 | sourceCompatibility = 1.7
65 | sourceSets.main.java.srcDirs = [ "src/" ]
66 |
67 |
68 | eclipse.project {
69 | name = appName + "-html"
70 | }
71 |
--------------------------------------------------------------------------------
/html/src/com/meizu/taskmanager/GdxDefinition.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/html/src/com/meizu/taskmanager/GdxDefinitionSuperdev.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/html/src/com/meizu/taskmanager/client/HtmlLauncher.java:
--------------------------------------------------------------------------------
1 | package com.meizu.taskmanager.client;
2 |
3 | import com.badlogic.gdx.ApplicationListener;
4 | import com.badlogic.gdx.backends.gwt.GwtApplication;
5 | import com.badlogic.gdx.backends.gwt.GwtApplicationConfiguration;
6 | import com.meizu.taskmanager.TaskManager;
7 |
8 | public class HtmlLauncher extends GwtApplication {
9 |
10 | @Override
11 | public GwtApplicationConfiguration getConfig () {
12 | return new GwtApplicationConfiguration(480, 320);
13 | }
14 |
15 | @Override
16 | public ApplicationListener getApplicationListener () {
17 | return new TaskManager();
18 | }
19 | }
--------------------------------------------------------------------------------
/html/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/html/webapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TaskManager
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ↻
13 |
14 |
15 |
16 |
17 |
32 |
33 |
--------------------------------------------------------------------------------
/html/webapp/refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/html/webapp/refresh.png
--------------------------------------------------------------------------------
/html/webapp/soundmanager2-jsmin.js:
--------------------------------------------------------------------------------
1 | /** @license
2 |
3 |
4 | SoundManager 2: JavaScript Sound for the Web
5 | ----------------------------------------------
6 | http://schillmania.com/projects/soundmanager2/
7 |
8 | Copyright (c) 2007, Scott Schiller. All rights reserved.
9 | Code provided under the BSD License:
10 | http://schillmania.com/projects/soundmanager2/license.txt
11 |
12 | V2.97a.20130512
13 | */
14 | (function(h,g){function fa(fa,wa){function ga(b){return c.preferFlash&&H&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function s(b){return function(d){var e=this._s;!e||!e._a?(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD(rb+"Ignoring "+d.type),d=null):d=b.call(this,d);return d}}this.setupOptions={url:fa||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,
15 | wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1,idPrefix:"sound"};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,
16 | usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs\x3d"mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs\x3d"mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs\x3dvorbis"],required:!1},
17 | opus:{type:["audio/ogg; codecs\x3dopus","audio/opus"],required:!1},wav:{type:['audio/wav; codecs\x3d"1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=wa||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20130512";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns=
18 | {flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=
19 | !1;var Ua,c=this,Va=null,k=null,rb="HTML5::",A,t=navigator.userAgent,U=h.location.href.toString(),m=document,xa,Wa,ya,n,F=[],za=!0,C,V=!1,W=!1,q=!1,y=!1,ha=!1,p,sb=0,X,B,Aa,O,Ba,M,P,Q,Xa,Ca,ia,I,ja,Da,R,Ea,Y,ka,la,S,Ya,Fa,Za=["log","info","warn","error"],$a,Ga,ab,Z=null,Ha=null,r,Ia,T,bb,ma,na,J,v,$=!1,Ja=!1,cb,db,eb,oa=0,aa=null,pa,N=[],qa,u=null,fb,ra,ba,K,sa,Ka,gb,w,hb=Array.prototype.slice,E=!1,La,H,Ma,ib,G,jb,Na,ta,kb=0,ca=t.match(/(ipad|iphone|ipod)/i),lb=t.match(/android/i),L=t.match(/msie/i),
20 | tb=t.match(/webkit/i),ua=t.match(/safari/i)&&!t.match(/chrome/i),Oa=t.match(/opera/i),ub=t.match(/firefox/i),Pa=t.match(/(mobile|pre\/|xoom)/i)||ca||lb,Qa=!U.match(/usehtml5audio/i)&&!U.match(/sm2\-ignorebadua/i)&&ua&&!t.match(/silk/i)&&t.match(/OS X 10_6_([3-7])/i),da=h.console!==g&&console.log!==g,Ra=m.hasFocus!==g?m.hasFocus():null,va=ua&&(m.hasFocus===g||!m.hasFocus()),mb=!va,nb=/(mp3|mp4|mpa|m4a|m4b)/i,ea=m.location?m.location.protocol.match(/http/i):null,ob=!ea?"http://":"",pb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
21 | qb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),vb=RegExp("\\.("+qb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!ea;var Sa;try{Sa=Audio!==g&&(Oa&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(wb){Sa=!1}this.hasHTML5=Sa;this.setup=function(b){var d=!c.url;b!==g&&(q&&u&&c.ok()&&(b.flashVersion!==g||b.url!==g||b.html5Test!==g))&&J(r("setupLate"));Aa(b);b&&(d&&(Y&&b.url!==g)&&c.beginDelayedInit(),
22 | !Y&&(b.url!==g&&"complete"===m.readyState)&&setTimeout(R,1));return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return A(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=ma(f);c.sounds[f.id]=new Ua(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+r(!q?"notReady":"notOK");if(!q||!c.ok())return J(a),!1;d!==g&&(b={id:b,url:d});f=B(b);f.url=pa(f.url);void 0===f.id&&(f.id=c.setupOptions.idPrefix+
23 | kb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+r("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(v(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(ra(f))a=e(),c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."),e();if(c.html5.usingFlash&&f.url&&f.url.match(/data\:/i))return c._wD(f.id+
24 | ": data: URIs not supported via Flash. Exiting."),e();8a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+a.instanceCount+"..."),l=new Audio(a._iO.url),z=function(){w.remove(l,"onended",z);a._onfinish(a);sa(l);l=null},h=function(){w.remove(l,"canplay",h);try{l.currentTime=a._iO.position/1E3}catch(c){J(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}l.play()},w.add(l,"ended",z),a._iO.position?
45 | w.add(l,"canplay",h):l.play()):(x=k._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3,a._iO.multiShot||!1),9===n&&!x&&(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a)))}return a};this.stop=function(b){var d=a._iO;1===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Ta(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),
46 | a.playState=0,a._onTimer(),l()):(k._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount=0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(k._setAutoPlay(a.id,b),b&&(!a.instanceCount&&1===a.readyState)&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?
47 | Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&&a._onTimer(!0)}}else b=
48 | 9===n?a.position:b,a.readyState&&2!==a.readyState&&k._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),l()):(b||b===g)&&k._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),
49 | m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),k._pause(a.id,b.multiShot));!s&&b.onplay?(b.onplay.apply(a),s=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9===n&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||k._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=b);return a};this.setVolume=
50 | function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(a._a.volume=Math.max(0,Math.min(1,b/100))):k._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):k._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):k._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():
51 | a.mute()};this.onposition=this.onPosition=function(b,c,d){D.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c=b)return!1;for(b-=1;0<=b;b--)c=D[b],!c.fired&&a.position>=c.position&&(c.fired=!0,t++,c.method.apply(c.scope,[c.position]));
52 | return!0};this._resetOnPosition=function(a){var b,c;b=D.length;if(!b)return!1;for(b-=1;0<=b;b--)c=D[b],c.fired&&a<=c.position&&(c.fired=!1,t--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null!==d&&!isNaN(d)&&(b.position=d,b.multiShot=!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,
53 | 10),c[b])};Ta=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&cb(a)};l=function(){a.isHTML5&&db(a)};f=function(b){b||(D=[],t=0);s=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=
54 | 0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b){if(a._a&&(b||(0opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,E&&(Va=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in G)G.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,G[b],!1);return!0};z=function(){var b;c._wD(a.id+": Removing event listeners");
57 | a._a._added_events=!1;for(b in G)G.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,G[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(!a.duration?" Zero-length duration reported.":" -")+" ("+a.url+")"),d?1:2);!d&&!a.isHTML5&&(!0===c.sandbox.noRemote&&c._wD(b+r("noNet"),1),!0===c.sandbox.noLocal&&c._wD(b+r("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0);a._iO.onload&&ta(a,function(){a._iO.onload.apply(a,
58 | [d])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a));return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failures \x3d "+a.failures);if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(a,b,d,e);
59 | else c._wD(a.id+": Ignoring failure")};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);if(a.instanceCount&&(a.instanceCount--,a.instanceCount||(Ta(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},l(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b))c._wD(a.id+": onfinish()"),ta(a,function(){b.apply(a)})};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);
60 | a.bufferLength=e;a.durationEstimate=!a.isHTML5&&!f.isMovieStar?f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10):a.duration;a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var l=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8opera.version()?new Audio(null):new Audio:null,e,a,f={},h;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(nb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(a=h[e].related.length-
74 | 1;0<=a;a--)f["audio/"+h[e].related[a]]=f[e],c.html5[h[e].related[a]]=f[e],c.flash[h[e].related[a]]=f[e];f.canPlayType=d?b:null;c.html5=B(c.html5,f);c.html5.usingFlash=fb();u=c.html5.usingFlash;return!0};I={notReady:"Unavailable - wait until onready() has fired.",notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash \x3d true for more security details (output goes to SWF.)",
75 | checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+m.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",
76 | waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",
77 | secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",
78 | fbLoaded:"Flash loaded",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout \x3d 0 (infinite) for off-screen, mobile flash case",
79 | needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().",
80 | noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready.",reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device."};r=function(){var b=hb.call(arguments),c=b.shift(),c=I&&I[c]?I[c]:"",e,a;if(c&&b&&b.length){e=0;for(a=b.length;en)&&(c._wD(r("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":
83 | 9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8b&&(d=
102 | !0));setTimeout(function(){b=c.getMoviePercent();if(d)return $=!1,c._wD(r("waitSWF")),h.setTimeout(Q,1),!1;q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+r("checkSWF"):""),2),!ea&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(r("swf404",c.url),1),C("flashtojs",!1,": Timed out"+ea?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));
103 | !q&&mb&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ia(),p("waitForever")):!c.useFlashBlock&&qa?h.setTimeout(function(){J("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...");c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1):(p("waitForever"),M({type:"ontimeout",ignoreInit:!0})):0===c.flashLoadTimeout?p("waitForever"):Ga(!0))},c.flashLoadTimeout)};ia=function(){if(Ra||!va)return w.remove(h,"focus",
104 | ia),!0;Ra=mb=!0;p("gotFocus");$=!1;Q();w.remove(h,"focus",ia);return!0};Na=function(){N.length&&(c._wD("SoundManager 2: "+N.join(" "),1),N=[])};jb=function(){Na();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" \x3d "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&u?" (preferring flash)":!c.html5[b]?" ("+(c.audioFormats[b].required?"required, ":"")+"and no flash support)":""));c._wD("SoundManager 2 HTML5 support: "+
105 | d.join(", "),1)}};X=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded"),q=!0,P(),C("onload",!0),!0;var d=!0,e;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())q=!0,y&&(e={type:!H&&u?"NO_FLASH":"INIT_TIMEOUT"});c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+")",y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className=T()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),M({type:"ontimeout",error:e,ignoreInit:!0}),C("onload",
106 | !1),S(e),d=!1):C("onload",!0);y||(c.waitForWindowLoad&&!ha?(p("waitOnload"),w.add(h,"load",P)):(c.waitForWindowLoad&&ha&&p("docLoaded"),P()));return d};Wa=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};ya=function(){if(q)return p("didInit"),!1;if(c.html5Only)return q||(w.remove(h,"load",c.beginDelayedInit),c.enabled=!0,X()),!0;ja();try{k._externalInterfaceTest(!1),Ya(!0,c.flashPollingInterval||(c.useHighPerformance?10:
107 | 50)),c.debugMode||k._disableDebug(),c.enabled=!0,C("jstoflash",!0),c.html5Only||w.add(h,"unload",xa)}catch(b){return c._wD("js/flash exception: "+b.toString()),C("jstoflash",!1),S({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ga(!0),X(),!1}X();w.remove(h,"load",c.beginDelayedInit);return!0};R=function(){if(Y)return!1;Y=!0;Wa();Fa();var b=null,b=null,d=U.toLowerCase();-1!==d.indexOf("sm2-usehtml5audio\x3d")&&(b="1"===d.charAt(d.indexOf("sm2-usehtml5audio\x3d")+18),da&&console.log((b?"Enabling ":"Disabling ")+
108 | "useHTML5Audio via URL parameter"),c.setup({useHTML5Audio:b}));-1!==d.indexOf("sm2-preferflash\x3d")&&(b="1"===d.charAt(d.indexOf("sm2-preferflash\x3d")+16),da&&console.log((b?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.setup({preferFlash:b}));!H&&c.hasHTML5&&(c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));gb();!H&&u&&(N.push(I.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&
109 | m.removeEventListener("DOMContentLoaded",R,!1);ja();return!0};Ka=function(){"complete"===m.readyState&&(R(),m.detachEvent("onreadystatechange",Ka));return!0};Ea=function(){ha=!0;w.remove(h,"load",Ea)};Da=function(){if(Pa&&((!c.setupOptions.useHTML5Audio||c.setupOptions.preferFlash)&&N.push(I.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,ca||lb&&!t.match(/android\s2\.3/i)))N.push(I.globalHTML5),ca&&(c.ignoreFlash=!0),E=!0};Da();Ma();w.add(h,"focus",ia);w.add(h,"load",Q);w.add(h,
110 | "load",Ea);m.addEventListener?m.addEventListener("DOMContentLoaded",R,!1):m.attachEvent?m.attachEvent("onreadystatechange",Ka):(C("onload",!1),S({type:"NO_DOM2_EVENTS",fatal:!0}))}var wa=null;if(void 0===h.SM2_DEFER||!SM2_DEFER)wa=new fa;h.SoundManager=fa;h.soundManager=wa})(window);
--------------------------------------------------------------------------------
/html/webapp/soundmanager2-setup.js:
--------------------------------------------------------------------------------
1 | window.SM2_DEFER = true;
--------------------------------------------------------------------------------
/html/webapp/styles.css:
--------------------------------------------------------------------------------
1 | canvas {
2 | cursor: default;
3 | outline: none;
4 | }
5 |
6 | body {
7 | background-color: #222222;
8 | }
9 |
10 | .superdev {
11 | color: rgb(37,37,37);
12 | text-shadow: 0px 1px 1px rgba(250,250,250,0.1);
13 | font-size: 50pt;
14 | display: block;
15 | position: relative;
16 | text-decoration: none;
17 | background-color: rgb(83,87,93);
18 | box-shadow: 0px 3px 0px 0px rgb(34,34,34),
19 | 0px 7px 10px 0px rgb(17,17,17),
20 | inset 0px 1px 1px 0px rgba(250, 250, 250, .2),
21 | inset 0px -12px 35px 0px rgba(0, 0, 0, .5);
22 | width: 70px;
23 | height: 70px;
24 | border: 0;
25 | border-radius: 35px;
26 | text-align: center;
27 | line-height: 68px;
28 | }
29 |
30 | .superdev:active {
31 | box-shadow: 0px 0px 0px 0px rgb(34,34,34),
32 | 0px 3px 7px 0px rgb(17,17,17),
33 | inset 0px 1px 1px 0px rgba(250, 250, 250, .2),
34 | inset 0px -10px 35px 5px rgba(0, 0, 0, .5);
35 | background-color: rgb(83,87,93);
36 | top: 3px;
37 | color: #fff;
38 | text-shadow: 0px 0px 3px rgb(250,250,250);
39 | }
40 |
41 | .superdev:hover {
42 | background-color: rgb(100,100,100);
43 | }
44 |
--------------------------------------------------------------------------------
/screen-record.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenaiX/TaskManager/22596a45f0f8a5d5b8bc3f06d66de51827d57346/screen-record.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'desktop'
2 | include 'android'
3 | include 'html'
4 | include 'core'
--------------------------------------------------------------------------------