├── .gitignore ├── .idea ├── caches │ ├── build_file_checksums.ser │ └── gradle_models.ser ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── modules.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── cyanogenmod │ │ └── designertools │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── org │ │ │ └── cyanogenmod │ │ │ └── designertools │ │ │ ├── DesignerToolsApplication.java │ │ │ ├── overlays │ │ │ ├── ColorPickerOverlay.java │ │ │ ├── GridOverlay.java │ │ │ └── MockOverlay.java │ │ │ ├── receiver │ │ │ └── BootReceiver.java │ │ │ ├── service │ │ │ ├── ScreenshotInfoService.java │ │ │ ├── ScreenshotListenerService.java │ │ │ └── qs │ │ │ │ ├── ColorPickerTileService.java │ │ │ │ ├── GridOverlayTileService.java │ │ │ │ └── MockOverlayTileService.java │ │ │ ├── ui │ │ │ ├── AppShortcutsActivity.java │ │ │ ├── ColorPickerCardFragment.java │ │ │ ├── CreditsActivity.java │ │ │ ├── DesignerToolCardFragment.java │ │ │ ├── DesignerToolsActivity.java │ │ │ ├── DualColorPickerDialog.java │ │ │ ├── GridOverlayCardFragment.java │ │ │ ├── MockupOverlayCardFragmnt.java │ │ │ ├── ScreenRecordRequestActivity.java │ │ │ ├── ScreenshotCardFragment.java │ │ │ └── StartOverlayActivity.java │ │ │ ├── utils │ │ │ ├── ColorUtils.java │ │ │ ├── ImageUtils.java │ │ │ ├── LaunchUtils.java │ │ │ ├── LayoutRenderUtils.java │ │ │ ├── MockupUtils.java │ │ │ ├── NotificationUtils.java │ │ │ ├── PreferenceUtils.java │ │ │ └── ViewUtils.java │ │ │ └── widget │ │ │ ├── DualColorPicker.java │ │ │ ├── GridPreview.java │ │ │ ├── MagnifierNodeView.java │ │ │ ├── MagnifierView.java │ │ │ └── VerticalSeekBar.java │ └── res │ │ ├── drawable-hdpi │ │ ├── color_hex_backer.9.png │ │ ├── ic_header_glyph.png │ │ ├── ic_launcher.png │ │ └── loop_ring.png │ │ ├── drawable-mdpi │ │ ├── color_hex_backer.9.png │ │ ├── ic_header_glyph.png │ │ ├── ic_launcher.png │ │ └── loop_ring.png │ │ ├── drawable-nodpi │ │ ├── aaron.png │ │ ├── asher.png │ │ ├── clark.png │ │ ├── img_header_bg.png │ │ └── kover.png │ │ ├── drawable-xhdpi │ │ ├── color_hex_backer.9.png │ │ ├── ic_header_glyph.png │ │ ├── ic_launcher.png │ │ └── loop_ring.png │ │ ├── drawable-xxhdpi │ │ ├── color_hex_backer.9.png │ │ ├── ic_header_glyph.png │ │ ├── ic_launcher.png │ │ └── loop_ring.png │ │ ├── drawable-xxxhdpi │ │ ├── color_hex_backer.9.png │ │ ├── ic_launcher.png │ │ └── loop_ring.png │ │ ├── drawable │ │ ├── card_background.xml │ │ ├── half_circle_left.xml │ │ ├── ic_add.xml │ │ ├── ic_header_glyph.xml │ │ ├── ic_marker_horiz_left.xml │ │ ├── ic_marker_horiz_right.xml │ │ ├── ic_marker_vert.xml │ │ ├── ic_qs_colorpicker_off.xml │ │ ├── ic_qs_colorpicker_on.xml │ │ ├── ic_qs_grid_off.xml │ │ ├── ic_qs_grid_on.xml │ │ ├── ic_qs_layoutbounds_off.xml │ │ ├── ic_qs_layoutbounds_on.xml │ │ ├── ic_qs_overlay_off.xml │ │ ├── ic_qs_overlay_on.xml │ │ ├── ic_qs_screenshotinfo_off.xml │ │ ├── ic_qs_screenshotinfo_on.xml │ │ ├── ic_shortcut_colorpicker.xml │ │ ├── ic_shortcut_grid.xml │ │ ├── ic_shortcut_mock.xml │ │ ├── loop_node.xml │ │ ├── pick_mock_overlay_background.xml │ │ └── pick_mockup_frame.xml │ │ ├── layout-land │ │ ├── activity_designer_tools.xml │ │ └── app_header.xml │ │ ├── layout-w600dp │ │ └── activity_designer_tools.xml │ │ ├── layout │ │ ├── activity_credits.xml │ │ ├── activity_designer_tools.xml │ │ ├── app_header.xml │ │ ├── card_header.xml │ │ ├── card_layout.xml │ │ ├── color_picker_magnifier.xml │ │ ├── credits_header.xml │ │ ├── dialog_color_picker.xml │ │ ├── grid_overlay_content.xml │ │ ├── lobsterpicker.xml │ │ ├── mockup_overlay_content.xml │ │ └── screenshot_info.xml │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ │ ├── values-land │ │ └── dimens.xml │ │ ├── values-w600dp │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── integers.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── app_shortcuts.xml │ └── test │ └── java │ └── org │ └── cyanogenmod │ └── designertools │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── designer_tools.png └── quick_settings_tiles.png ├── projectFilesBackup └── .idea │ └── workspace.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle files 2 | .gradle/ 3 | build/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Log/OS Files 9 | *.log 10 | 11 | # Android Studio generated files and folders 12 | captures/ 13 | .externalNativeBuild/ 14 | .cxx/ 15 | *.apk 16 | output.json 17 | 18 | # IntelliJ 19 | *.iml 20 | .idea/ 21 | misc.xml 22 | deploymentTargetDropDown.xml 23 | render.experimental.xml 24 | 25 | # Keystore files 26 | *.jks 27 | *.keystore 28 | 29 | # Google Services (e.g. APIs or Firebase) 30 | google-services.json 31 | 32 | # Android Profiling 33 | *.hprof 34 | 35 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Designer Tools 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdk 33 5 | 6 | defaultConfig { 7 | applicationId "com.scheffsblend.designertools" 8 | minSdkVersion 24 9 | targetSdkVersion 33 10 | versionCode 6 11 | versionName "2.2.2" 12 | setProperty("archivesBaseName", "DesignerTools-$versionName") 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled true 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | dependenciesInfo { 25 | includeInApk true 26 | includeInBundle true 27 | } 28 | buildToolsVersion '33.0.0' 29 | namespace 'org.cyanogenmod.designertools' 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(include: ['*.jar'], dir: 'libs') 34 | testImplementation 'junit:junit:4.12' 35 | implementation 'androidx.appcompat:appcompat:1.5.1' 36 | implementation 'com.larswerkman:lobsterpicker:1.0.1' 37 | implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\clark\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/org/cyanogenmod/designertools/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package org.cyanogenmod.designertools; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 41 | 42 | 46 | 47 | 50 | 51 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 95 | 96 | 97 | 98 | 99 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/DesignerToolsApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools; 17 | 18 | import android.app.Activity; 19 | import android.app.Application; 20 | import android.content.Intent; 21 | 22 | import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; 23 | import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; 24 | import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; 25 | 26 | public class DesignerToolsApplication extends Application { 27 | 28 | private int mResultCode = Activity.RESULT_CANCELED; 29 | private Intent mResultData; 30 | 31 | private boolean mGridOverlayOn; 32 | private boolean mMockOverlayOn; 33 | private boolean mColorPickerOn; 34 | private boolean mScreenshotOn; 35 | 36 | public void setScreenRecordPermissionData(int resultCode, Intent resultData) { 37 | mResultCode = resultCode; 38 | mResultData = resultData; 39 | } 40 | 41 | public int getScreenRecordResultCode() { 42 | return mResultCode; 43 | } 44 | 45 | public Intent getScreenRecordResultData() { 46 | return mResultData; 47 | } 48 | 49 | public void setGridOverlayOn(boolean on) { 50 | mGridOverlayOn = on; 51 | } 52 | 53 | public boolean getGridOverlayOn() { 54 | return mGridOverlayOn || GridPreferences.getGridQsTileEnabled(this, false); 55 | } 56 | 57 | public void setMockOverlayOn(boolean on) { 58 | mMockOverlayOn = on; 59 | } 60 | 61 | public boolean getMockOverlayOn() { 62 | return mMockOverlayOn || MockPreferences.getMockQsTileEnabled(this, false); 63 | } 64 | 65 | public void setColorPickerOn(boolean on) { 66 | mColorPickerOn = on; 67 | } 68 | 69 | public boolean getColorPickerOn() { 70 | return mColorPickerOn || ColorPickerPreferences.getColorPickerQsTileEnabled(this, false); 71 | } 72 | 73 | public void setScreenshotOn(boolean on) { 74 | mScreenshotOn = on; 75 | } 76 | 77 | public boolean getScreenshotOn() { 78 | return mScreenshotOn; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/receiver/BootReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.receiver; 17 | 18 | import android.content.BroadcastReceiver; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | 22 | import org.cyanogenmod.designertools.service.ScreenshotListenerService; 23 | import org.cyanogenmod.designertools.utils.PreferenceUtils; 24 | 25 | public class BootReceiver extends BroadcastReceiver { 26 | public BootReceiver() { 27 | } 28 | 29 | @Override 30 | public void onReceive(Context context, Intent intent) { 31 | if (PreferenceUtils.GridPreferences.getGridQsTileEnabled(context, false)) { 32 | PreferenceUtils.GridPreferences.setGridOverlayActive(context, false); 33 | } 34 | if (PreferenceUtils.MockPreferences.getMockQsTileEnabled(context, false)) { 35 | PreferenceUtils.MockPreferences.setMockOverlayActive(context, false); 36 | } 37 | if (PreferenceUtils.ColorPickerPreferences.getColorPickerQsTileEnabled(context, false)) { 38 | PreferenceUtils.ColorPickerPreferences.setColorPickerActive(context, false); 39 | } 40 | if (PreferenceUtils.ScreenshotPreferences.getScreenshotInfoEnabled(context, false)) { 41 | Intent newIntent = new Intent(context, ScreenshotListenerService.class); 42 | context.startService(newIntent); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/service/ScreenshotListenerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.service; 17 | 18 | import android.app.Notification; 19 | import android.app.PendingIntent; 20 | import android.app.Service; 21 | import android.content.Intent; 22 | import android.content.SharedPreferences; 23 | import android.database.ContentObserver; 24 | import android.database.Cursor; 25 | import android.net.Uri; 26 | import android.os.Handler; 27 | import android.os.IBinder; 28 | import android.provider.MediaStore; 29 | import android.util.Log; 30 | 31 | import org.cyanogenmod.designertools.R; 32 | import org.cyanogenmod.designertools.ui.DesignerToolsActivity; 33 | import org.cyanogenmod.designertools.utils.NotificationUtils; 34 | import org.cyanogenmod.designertools.utils.PreferenceUtils; 35 | import org.cyanogenmod.designertools.utils.PreferenceUtils.ScreenshotPreferences; 36 | 37 | public class ScreenshotListenerService extends Service 38 | implements SharedPreferences.OnSharedPreferenceChangeListener { 39 | private static final String CHANNEL_ID = "DesignerTools.ScreenshotListenerService"; 40 | 41 | private ScreenShotObserver mScreenshotObserver; 42 | 43 | @Override 44 | public IBinder onBind(Intent intent) { 45 | return null; 46 | } 47 | 48 | @Override 49 | public void onCreate() { 50 | super.onCreate(); 51 | PreferenceUtils.getShardedPreferences(this).registerOnSharedPreferenceChangeListener(this); 52 | startForeground(42, getPersistentNotification()); 53 | } 54 | 55 | @Override 56 | public int onStartCommand(Intent intent, int flags, int startId) { 57 | if (mScreenshotObserver == null) { 58 | mScreenshotObserver = new ScreenShotObserver(new Handler()); 59 | getContentResolver().registerContentObserver( 60 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mScreenshotObserver); 61 | } 62 | return START_STICKY; 63 | } 64 | 65 | @Override 66 | public void onDestroy() { 67 | super.onDestroy(); 68 | PreferenceUtils.getShardedPreferences(this) 69 | .unregisterOnSharedPreferenceChangeListener(this); 70 | if (mScreenshotObserver != null) { 71 | getContentResolver().unregisterContentObserver(mScreenshotObserver); 72 | } 73 | } 74 | 75 | @Override 76 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 77 | if (ScreenshotPreferences.KEY_SCREENSHOT_INFO.equals(key)) { 78 | boolean enabled = ScreenshotPreferences.getScreenshotInfoEnabled(this, false); 79 | if (!enabled) { 80 | stopSelf(); 81 | } 82 | } 83 | } 84 | 85 | private Notification getPersistentNotification() { 86 | final PendingIntent pi = PendingIntent.getActivity( 87 | this, 88 | 0, 89 | new Intent(this, DesignerToolsActivity.class), 90 | PendingIntent.FLAG_IMMUTABLE); 91 | final String contentText = getString(R.string.notif_content_screenshot_info); 92 | 93 | return NotificationUtils.createForegroundServiceNotification( 94 | this, 95 | CHANNEL_ID, 96 | R.drawable.ic_qs_screenshotinfo_on, 97 | getString(R.string.screenshot_qs_tile_label), 98 | contentText, 99 | pi); 100 | } 101 | 102 | private class ScreenShotObserver extends ContentObserver { 103 | private final String TAG = ScreenShotObserver.class.getSimpleName(); 104 | private final String EXTERNAL_CONTENT_URI_MATCHER = 105 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString(); 106 | private final String[] PROJECTION = new String[] { 107 | MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.DATA, 108 | MediaStore.Images.Media.DATE_TAKEN 109 | }; 110 | private static final String SORT_ORDER = MediaStore.Images.Media.DATE_ADDED + " DESC"; 111 | private static final long ADD_INFO_DELAY_MS = 1000; 112 | 113 | private String mLastProcessedImage = null; 114 | private Handler mHandler; 115 | 116 | ScreenShotObserver(Handler handler) { 117 | super(handler); 118 | mHandler = handler; 119 | } 120 | 121 | @Override 122 | public void onChange(boolean selfChange, Uri uri) { 123 | if (uri.toString().startsWith(EXTERNAL_CONTENT_URI_MATCHER)) { 124 | try (Cursor cursor = getContentResolver().query(uri, PROJECTION, null, null, 125 | SORT_ORDER)) { 126 | if (cursor != null && cursor.moveToFirst()) { 127 | String path = cursor.getString( 128 | cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)); 129 | if (path.substring(path.lastIndexOf("/") + 1).toLowerCase().startsWith("screenshot") && 130 | !path.equals(mLastProcessedImage)) { 131 | mLastProcessedImage = path; 132 | final Intent intent = 133 | new Intent(ScreenshotListenerService.this, 134 | ScreenshotInfoService.class); 135 | intent.putExtra(ScreenshotInfoService.EXTRA_URI, uri); 136 | // give time for screenshot to be fully written to storage 137 | mHandler.postDelayed(new Runnable() { 138 | @Override 139 | public void run() { 140 | startService(intent); 141 | } 142 | }, ADD_INFO_DELAY_MS); 143 | } 144 | } 145 | } catch (Exception e) { 146 | Log.e(TAG, "open cursor fail", e); 147 | } 148 | } 149 | super.onChange(selfChange, uri); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/service/qs/ColorPickerTileService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.service.qs; 17 | 18 | import android.graphics.drawable.Icon; 19 | import android.service.quicksettings.Tile; 20 | import android.service.quicksettings.TileService; 21 | 22 | import org.cyanogenmod.designertools.DesignerToolsApplication; 23 | import org.cyanogenmod.designertools.R; 24 | import org.cyanogenmod.designertools.utils.LaunchUtils; 25 | 26 | public class ColorPickerTileService extends TileService { 27 | public ColorPickerTileService() { 28 | super(); 29 | } 30 | 31 | @Override 32 | public void onTileAdded() { 33 | super.onTileAdded(); 34 | final Tile tile = getQsTile(); 35 | tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_colorpicker_on)); 36 | } 37 | 38 | @Override 39 | public void onTileRemoved() { 40 | super.onTileRemoved(); 41 | } 42 | 43 | @Override 44 | public void onStartListening() { 45 | super.onStartListening(); 46 | updateTile(((DesignerToolsApplication) getApplication()).getColorPickerOn()); 47 | } 48 | 49 | @Override 50 | public void onStopListening() { 51 | super.onStopListening(); 52 | } 53 | 54 | @Override 55 | public void onClick() { 56 | super.onClick(); 57 | boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getColorPickerOn(); 58 | if (isOn) { 59 | LaunchUtils.cancelColorPickerOverlay(this); 60 | } else { 61 | LaunchUtils.launchColorPickerOverlay(this); 62 | } 63 | updateTile(!isOn); 64 | } 65 | 66 | private void updateTile(boolean isOn) { 67 | final Tile tile = getQsTile(); 68 | tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); 69 | tile.updateTile(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/service/qs/GridOverlayTileService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.service.qs; 17 | 18 | import android.graphics.drawable.Icon; 19 | import android.service.quicksettings.Tile; 20 | import android.service.quicksettings.TileService; 21 | 22 | import org.cyanogenmod.designertools.DesignerToolsApplication; 23 | import org.cyanogenmod.designertools.R; 24 | import org.cyanogenmod.designertools.utils.LaunchUtils; 25 | 26 | public class GridOverlayTileService extends TileService { 27 | public GridOverlayTileService() { 28 | super(); 29 | } 30 | 31 | @Override 32 | public void onTileAdded() { 33 | super.onTileAdded(); 34 | final Tile tile = getQsTile(); 35 | tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_grid_on)); 36 | } 37 | 38 | @Override 39 | public void onTileRemoved() { 40 | super.onTileRemoved(); 41 | } 42 | 43 | @Override 44 | public void onStartListening() { 45 | super.onStartListening(); 46 | boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getGridOverlayOn(); 47 | updateTile(isOn); 48 | } 49 | 50 | @Override 51 | public void onStopListening() { 52 | super.onStopListening(); 53 | } 54 | 55 | @Override 56 | public void onClick() { 57 | super.onClick(); 58 | boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getGridOverlayOn(); 59 | if (isOn) { 60 | LaunchUtils.cancelGridOverlay(this); 61 | } else { 62 | LaunchUtils.launchGridOverlay(this); 63 | } 64 | updateTile(!isOn); 65 | } 66 | 67 | private void updateTile(boolean isOn) { 68 | final Tile tile = getQsTile(); 69 | tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); 70 | tile.updateTile(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/service/qs/MockOverlayTileService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.service.qs; 17 | 18 | import android.graphics.drawable.Icon; 19 | import android.service.quicksettings.Tile; 20 | import android.service.quicksettings.TileService; 21 | 22 | import org.cyanogenmod.designertools.DesignerToolsApplication; 23 | import org.cyanogenmod.designertools.R; 24 | import org.cyanogenmod.designertools.utils.LaunchUtils; 25 | 26 | public class MockOverlayTileService extends TileService { 27 | public MockOverlayTileService() { 28 | super(); 29 | } 30 | 31 | @Override 32 | public void onTileAdded() { 33 | super.onTileAdded(); 34 | final Tile tile = getQsTile(); 35 | tile.setIcon(Icon.createWithResource(this, R.drawable.ic_qs_overlay_on)); 36 | } 37 | 38 | @Override 39 | public void onTileRemoved() { 40 | super.onTileRemoved(); 41 | } 42 | 43 | @Override 44 | public void onStartListening() { 45 | super.onStartListening(); 46 | updateTile(((DesignerToolsApplication) getApplicationContext()).getMockOverlayOn()); 47 | } 48 | 49 | @Override 50 | public void onStopListening() { 51 | super.onStopListening(); 52 | } 53 | 54 | @Override 55 | public void onClick() { 56 | super.onClick(); 57 | boolean isOn = ((DesignerToolsApplication) getApplicationContext()).getMockOverlayOn(); 58 | if (isOn) { 59 | LaunchUtils.cancelMockOverlay(this); 60 | } else { 61 | LaunchUtils.launchMockOverlay(this); 62 | } 63 | updateTile(!isOn); 64 | } 65 | 66 | private void updateTile(boolean isOn) { 67 | final Tile tile = getQsTile(); 68 | tile.setState(isOn ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); 69 | tile.updateTile(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/AppShortcutsActivity.java: -------------------------------------------------------------------------------- 1 | package org.cyanogenmod.designertools.ui; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import org.cyanogenmod.designertools.DesignerToolsApplication; 8 | import org.cyanogenmod.designertools.utils.LaunchUtils; 9 | 10 | /** 11 | * Created by clark on 12/19/16. 12 | */ 13 | 14 | public class AppShortcutsActivity extends Activity { 15 | private static final String ACTION_SHOW_GRID_OVERLAY = 16 | "com.scheffsblend.designertools.action.SHOW_GRID_OVERLAY"; 17 | private static final String ACTION_SHOW_MOCK_OVERLAY = 18 | "com.scheffsblend.designertools.action.SHOW_MOCK_OVERLAY"; 19 | private static final String ACTION_SHOW_COLOR_PICKER_OVERLAY = 20 | "com.scheffsblend.designertools.action.SHOW_COLOR_PICKER_OVERLAY"; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | final Intent intent = getIntent(); 26 | final String action = intent.getAction(); 27 | if (ACTION_SHOW_GRID_OVERLAY.equals(action)) { 28 | toggleGridOverlay(); 29 | } else if (ACTION_SHOW_MOCK_OVERLAY.equals(action)) { 30 | toggleMockOverlay(); 31 | } else if (ACTION_SHOW_COLOR_PICKER_OVERLAY.equals(action)) { 32 | toggleColorPickerOverlay(); 33 | } 34 | finish(); 35 | } 36 | 37 | private DesignerToolsApplication getDesignerToolsApplication() { 38 | return (DesignerToolsApplication) getApplication(); 39 | } 40 | 41 | private void toggleGridOverlay() { 42 | if (getDesignerToolsApplication().getGridOverlayOn()) { 43 | LaunchUtils.cancelGridOverlay(this); 44 | } else { 45 | LaunchUtils.launchGridOverlay(this); 46 | } 47 | } 48 | 49 | private void toggleMockOverlay() { 50 | if (getDesignerToolsApplication().getMockOverlayOn()) { 51 | LaunchUtils.cancelMockOverlay(this); 52 | } else { 53 | LaunchUtils.launchMockOverlay(this); 54 | } 55 | } 56 | 57 | private void toggleColorPickerOverlay() { 58 | if (getDesignerToolsApplication().getColorPickerOn()) { 59 | LaunchUtils.cancelColorPickerOverlay(this); 60 | } else { 61 | LaunchUtils.launchColorPickerOverlay(this); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/ColorPickerCardFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.content.Intent; 19 | import android.content.res.ColorStateList; 20 | import android.os.Bundle; 21 | import android.provider.Settings; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.CompoundButton; 26 | 27 | import org.cyanogenmod.designertools.R; 28 | import org.cyanogenmod.designertools.utils.LaunchUtils; 29 | 30 | public class ColorPickerCardFragment extends DesignerToolCardFragment { 31 | private static final int REQUEST_OVERLAY_PERMISSION = 0x42; 32 | 33 | @Override 34 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 35 | Bundle savedInstanceState) { 36 | View base = super.onCreateView(inflater, container, savedInstanceState); 37 | setTitleText(R.string.header_title_color_picker); 38 | setTitleSummary(R.string.header_summary_color_picker); 39 | setIconResource(R.drawable.ic_qs_colorpicker_on); 40 | base.setBackgroundTintList(ColorStateList.valueOf( 41 | getActivity().getColor(R.color.colorColorPickerCardTint))); 42 | 43 | return base; 44 | } 45 | 46 | @Override 47 | public void onResume() { 48 | super.onResume(); 49 | mEnabledSwitch.setChecked(getApplicationContext().getColorPickerOn()); 50 | } 51 | 52 | @Override 53 | protected int getCardStyleResourceId() { 54 | return R.style.AppTheme_ColorPickerCard; 55 | } 56 | 57 | @Override 58 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 59 | if (isChecked == getApplicationContext().getColorPickerOn()) return; 60 | if (isChecked) { 61 | enableFeature(true); 62 | } else { 63 | enableFeature(false); 64 | } 65 | } 66 | 67 | @Override 68 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 69 | if (requestCode == REQUEST_OVERLAY_PERMISSION) { 70 | if (Settings.canDrawOverlays(getContext())) { 71 | mEnabledSwitch.setChecked(true); 72 | } else { 73 | mEnabledSwitch.setChecked(false); 74 | } 75 | } 76 | super.onActivityResult(requestCode, resultCode, data); 77 | } 78 | 79 | private void isEnabled() { 80 | } 81 | 82 | private void enableFeature(boolean enable) { 83 | if (enable) { 84 | LaunchUtils.launchColorPickerOverlay(getContext()); 85 | } else { 86 | LaunchUtils.cancelColorPickerOverlay(getContext()); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/CreditsActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.animation.Animator; 19 | import android.animation.AnimatorSet; 20 | import android.animation.ObjectAnimator; 21 | import android.app.Activity; 22 | import android.os.Bundle; 23 | import androidx.interpolator.view.animation.FastOutSlowInInterpolator; 24 | import android.view.View; 25 | import android.view.ViewAnimationUtils; 26 | import android.view.ViewTreeObserver; 27 | import android.view.animation.AccelerateDecelerateInterpolator; 28 | import android.view.animation.Interpolator; 29 | 30 | import org.cyanogenmod.designertools.R; 31 | 32 | public class CreditsActivity extends Activity { 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | overridePendingTransition(0, 0); 38 | setContentView(R.layout.activity_credits); 39 | } 40 | 41 | private void circularRevealActivity(View v) { 42 | 43 | int cx = v.getWidth() / 2; 44 | int cy = v.getHeight() / 2; 45 | 46 | float finalRadius = Math.max(v.getWidth(), v.getHeight()); 47 | 48 | // create the animator for this view (the start radius is zero) 49 | Animator circularReveal = ViewAnimationUtils 50 | .createCircularReveal(v, cx, cy, 0, finalRadius); 51 | circularReveal.setDuration(getResources().getInteger( 52 | R.integer.credits_circular_reveal_duration)); 53 | 54 | // make the view visible and start the animation 55 | v.setVisibility(View.VISIBLE); 56 | circularReveal.setInterpolator(new AccelerateDecelerateInterpolator()); 57 | circularReveal.addListener(new Animator.AnimatorListener() { 58 | @Override 59 | public void onAnimationStart(Animator animator) { 60 | } 61 | 62 | @Override 63 | public void onAnimationEnd(Animator animator) { 64 | animateContent(); 65 | } 66 | 67 | @Override 68 | public void onAnimationCancel(Animator animator) { 69 | } 70 | 71 | @Override 72 | public void onAnimationRepeat(Animator animator) { 73 | } 74 | }); 75 | circularReveal.start(); 76 | } 77 | 78 | @Override 79 | protected void onResume() { 80 | super.onResume(); 81 | final View rootLayout = findViewById(R.id.activity_credits); 82 | rootLayout.setVisibility(View.INVISIBLE); 83 | 84 | ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver(); 85 | if (viewTreeObserver.isAlive()) { 86 | viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 87 | @Override 88 | public void onGlobalLayout() { 89 | circularRevealActivity(rootLayout); 90 | rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 91 | } 92 | }); 93 | } 94 | } 95 | 96 | private void animateContent() { 97 | View avatar1 = findViewById(R.id.avatar1); 98 | avatar1.setScaleX(0); 99 | avatar1.setScaleY(0); 100 | avatar1.setVisibility(View.VISIBLE); 101 | View text1 = findViewById(R.id.text1); 102 | text1.setAlpha(0); 103 | text1.setVisibility(View.VISIBLE); 104 | View avatar2 = findViewById(R.id.avatar2); 105 | avatar2.setScaleX(0); 106 | avatar2.setScaleY(0); 107 | avatar2.setVisibility(View.VISIBLE); 108 | View text2 = findViewById(R.id.text2); 109 | text2.setAlpha(0); 110 | text2.setVisibility(View.VISIBLE); 111 | View avatar3 = findViewById(R.id.avatar3); 112 | avatar3.setScaleX(0); 113 | avatar3.setScaleY(0); 114 | avatar3.setVisibility(View.VISIBLE); 115 | View text3 = findViewById(R.id.text3); 116 | text3.setAlpha(0); 117 | text3.setVisibility(View.VISIBLE); 118 | View avatar4 = findViewById(R.id.avatar4); 119 | avatar4.setScaleX(0); 120 | avatar4.setScaleY(0); 121 | avatar4.setVisibility(View.VISIBLE); 122 | View text4 = findViewById(R.id.text4); 123 | text4.setAlpha(0); 124 | text4.setVisibility(View.VISIBLE); 125 | 126 | Interpolator interpolator = new FastOutSlowInInterpolator(); 127 | long duration = 375L; 128 | long delay = duration / 3; 129 | 130 | AnimatorSet anim1 = new AnimatorSet(); 131 | anim1.play(ObjectAnimator.ofFloat(avatar1, "scaleX", 1f)) 132 | .with(ObjectAnimator.ofFloat(avatar1, "scaleY", 1f)) 133 | .with(ObjectAnimator.ofFloat(text1, "alpha", 1f)); 134 | anim1.setDuration(duration); 135 | anim1.setInterpolator(interpolator); 136 | AnimatorSet anim2 = new AnimatorSet(); 137 | anim2.play(ObjectAnimator.ofFloat(avatar2, "scaleX", 1f)) 138 | .with(ObjectAnimator.ofFloat(avatar2, "scaleY", 1f)) 139 | .with(ObjectAnimator.ofFloat(text2, "alpha", 1f)); 140 | anim2.setDuration(duration); 141 | anim2.setInterpolator(interpolator); 142 | anim2.setStartDelay(delay); 143 | AnimatorSet anim3 = new AnimatorSet(); 144 | anim3.play(ObjectAnimator.ofFloat(avatar3, "scaleX", 1f)) 145 | .with(ObjectAnimator.ofFloat(avatar3, "scaleY", 1f)) 146 | .with(ObjectAnimator.ofFloat(text3, "alpha", 1f)); 147 | anim3.setDuration(duration); 148 | anim3.setInterpolator(interpolator); 149 | anim3.setStartDelay(delay * 2); 150 | AnimatorSet anim4 = new AnimatorSet(); 151 | anim4.play(ObjectAnimator.ofFloat(avatar4, "scaleX", 1f)) 152 | .with(ObjectAnimator.ofFloat(avatar4, "scaleY", 1f)) 153 | .with(ObjectAnimator.ofFloat(text4, "alpha", 1f)); 154 | anim4.setDuration(duration); 155 | anim4.setInterpolator(interpolator); 156 | anim4.setStartDelay(delay * 3); 157 | AnimatorSet set = new AnimatorSet(); 158 | set.play(anim1).with(anim2); 159 | set.play(anim2).with(anim3); 160 | set.play(anim3).with(anim4); 161 | set.start(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolCardFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.app.Fragment; 19 | import android.content.ContextWrapper; 20 | import android.content.res.ColorStateList; 21 | import android.os.Bundle; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.CompoundButton; 26 | import android.widget.FrameLayout; 27 | import android.widget.ImageView; 28 | import android.widget.Switch; 29 | import android.widget.TextView; 30 | 31 | import org.cyanogenmod.designertools.DesignerToolsApplication; 32 | import org.cyanogenmod.designertools.R; 33 | 34 | public class DesignerToolCardFragment extends Fragment 35 | implements CompoundButton.OnCheckedChangeListener { 36 | 37 | protected View mParentLayout; 38 | protected ImageView mIcon; 39 | protected TextView mHeaderTitle; 40 | protected TextView mHeaderSummary; 41 | protected Switch mEnabledSwitch; 42 | protected FrameLayout mCardContent; 43 | 44 | @Override 45 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 46 | Bundle savedInstanceState) { 47 | ContextWrapper ctx = new ContextWrapper(inflater.getContext()); 48 | ctx.setTheme(getCardStyleResourceId()); 49 | inflater.cloneInContext(ctx); 50 | View v = inflater.inflate(R.layout.card_layout, container, true); 51 | mParentLayout = v.findViewById(R.id.parent_layout); 52 | mIcon = v.findViewById(R.id.header_icon); 53 | mHeaderTitle = v.findViewById(R.id.header_title); 54 | mHeaderSummary = v.findViewById(R.id.header_summary); 55 | mEnabledSwitch = v.findViewById(R.id.enable_switch); 56 | mCardContent = v.findViewById(R.id.card_content); 57 | 58 | mEnabledSwitch.setOnCheckedChangeListener(this); 59 | 60 | return v; 61 | } 62 | 63 | protected void setIconResource(int resId) { 64 | if (mIcon != null) mIcon.setImageResource(resId); 65 | } 66 | 67 | protected void setTitleText(CharSequence text) { 68 | if (mHeaderTitle != null) mHeaderTitle.setText(text); 69 | } 70 | 71 | protected void setTitleText(int resId) { 72 | if (mHeaderTitle != null) mHeaderTitle.setText(resId); 73 | } 74 | 75 | protected void setTitleSummary(CharSequence text) { 76 | if (mHeaderSummary != null) mHeaderSummary.setText(text); 77 | } 78 | 79 | protected void setTitleSummary(int resId) { 80 | if (mHeaderSummary != null) mHeaderSummary.setText(resId); 81 | } 82 | 83 | protected void setBackgroundTintList(ColorStateList tint) { 84 | if (mParentLayout != null) mParentLayout.setBackgroundTintList(tint); 85 | } 86 | 87 | protected int getCardStyleResourceId() { 88 | return R.style.AppTheme; 89 | } 90 | 91 | protected DesignerToolsApplication getApplicationContext() { 92 | return (DesignerToolsApplication) getActivity().getApplicationContext(); 93 | } 94 | 95 | @Override 96 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/DesignerToolsActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.app.Activity; 19 | import android.content.Intent; 20 | import android.os.Bundle; 21 | import android.view.View; 22 | import android.widget.TextView; 23 | 24 | import org.cyanogenmod.designertools.R; 25 | import org.cyanogenmod.designertools.utils.LaunchUtils; 26 | 27 | public class DesignerToolsActivity extends Activity { 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_designer_tools); 33 | View headerGlyph = findViewById(R.id.header_glyph); 34 | if (headerGlyph != null) { 35 | headerGlyph.setOnClickListener(mGlyphClickListener); 36 | } 37 | } 38 | 39 | private View.OnClickListener mGlyphClickListener = new View.OnClickListener() { 40 | @Override 41 | public void onClick(View view) { 42 | startActivity(new Intent(DesignerToolsActivity.this, CreditsActivity.class)); 43 | } 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/ScreenRecordRequestActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.app.Activity; 19 | import android.content.Intent; 20 | import android.media.projection.MediaProjectionManager; 21 | import android.os.Bundle; 22 | 23 | import org.cyanogenmod.designertools.DesignerToolsApplication; 24 | import org.cyanogenmod.designertools.overlays.ColorPickerOverlay; 25 | import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; 26 | 27 | public class ScreenRecordRequestActivity extends Activity { 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | MediaProjectionManager mpm = getSystemService(MediaProjectionManager.class); 32 | startActivityForResult(mpm.createScreenCaptureIntent(), 42); 33 | } 34 | 35 | @Override 36 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 37 | if (resultCode == RESULT_OK) { 38 | ((DesignerToolsApplication) getApplication()).setScreenRecordPermissionData( 39 | resultCode, data); 40 | Intent newIntent = new Intent(this, ColorPickerOverlay.class); 41 | this.startService(newIntent); 42 | ColorPickerPreferences.setColorPickerActive(this, true); 43 | } 44 | finish(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/ScreenshotCardFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.Manifest; 19 | import android.app.AlertDialog; 20 | import android.content.Intent; 21 | import android.content.pm.PackageManager; 22 | import android.content.res.ColorStateList; 23 | import android.os.Build; 24 | import android.os.Bundle; 25 | import android.os.Environment; 26 | import android.provider.Settings; 27 | import android.view.LayoutInflater; 28 | import android.view.View; 29 | import android.view.ViewGroup; 30 | import android.widget.CompoundButton; 31 | 32 | import org.cyanogenmod.designertools.R; 33 | import org.cyanogenmod.designertools.service.ScreenshotListenerService; 34 | import org.cyanogenmod.designertools.utils.PreferenceUtils.ScreenshotPreferences; 35 | 36 | public class ScreenshotCardFragment extends DesignerToolCardFragment { 37 | private static final int REQUEST_CODE = 0x42; 38 | 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 41 | Bundle savedInstanceState) { 42 | View base = super.onCreateView(inflater, container, savedInstanceState); 43 | setTitleText(R.string.header_title_screenshot); 44 | setTitleSummary(R.string.header_summary_screenshot); 45 | setIconResource(R.drawable.ic_qs_screenshotinfo_on); 46 | base.setBackgroundTintList(ColorStateList.valueOf( 47 | getResources().getColor(R.color.colorScreenshotCardTint))); 48 | 49 | mEnabledSwitch.setChecked(ScreenshotPreferences.getScreenshotInfoEnabled(getContext(), 50 | false)); 51 | 52 | return base; 53 | } 54 | 55 | @Override 56 | public void onRequestPermissionsResult(int requestCode, String[] permissions, 57 | int[] grantResults) { 58 | if (hasRequiredPermissions()) { 59 | ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), true); 60 | Intent newIntent = new Intent(getContext(), ScreenshotListenerService.class); 61 | getContext().startService(newIntent); 62 | mEnabledSwitch.setChecked(true); 63 | } else { 64 | mEnabledSwitch.setChecked(false); 65 | } 66 | } 67 | 68 | @Override 69 | protected int getCardStyleResourceId() { 70 | return R.style.AppTheme_ScreenshotCard; 71 | } 72 | 73 | @Override 74 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 75 | if (isChecked) { 76 | if (hasRequiredPermissions()) { 77 | ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), true); 78 | Intent newIntent = new Intent(getContext(), ScreenshotListenerService.class); 79 | getContext().startService(newIntent); 80 | } else { 81 | mEnabledSwitch.setChecked(false); 82 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { 83 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE); 84 | } else { 85 | showReasoningDialog(); 86 | } 87 | } 88 | } else { 89 | ScreenshotPreferences.setScreenshotInfoEnabled(getContext(), false); 90 | } 91 | } 92 | 93 | private boolean hasRequiredPermissions() { 94 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { 95 | return getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) 96 | == PackageManager.PERMISSION_GRANTED; 97 | } else { 98 | return Environment.isExternalStorageManager(); 99 | } 100 | } 101 | 102 | private void requestAccessAllFilesPermission() { 103 | Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); 104 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 105 | getApplicationContext().startActivity(intent); 106 | } 107 | 108 | private void showReasoningDialog() { 109 | AlertDialog.Builder builder = 110 | new AlertDialog.Builder(getActivity(), R.style.AlertDialog); 111 | builder.setTitle(R.string.dialog_request_file_permission_title) 112 | .setMessage(R.string.dialog_request_file_permission_message) 113 | .setPositiveButton(R.string.dialog_request_file_permission_grant, (dialog, which) -> { 114 | requestAccessAllFilesPermission(); 115 | }) 116 | .setNegativeButton(R.string.dialog_request_file_permission_deny, (dialog, which) -> {}) 117 | .setIcon(R.drawable.ic_launcher) 118 | .show(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/ui/StartOverlayActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.ui; 17 | 18 | import android.app.Activity; 19 | import android.app.AlertDialog; 20 | import android.content.Intent; 21 | import android.net.Uri; 22 | import android.os.Bundle; 23 | import android.provider.Settings; 24 | 25 | import org.cyanogenmod.designertools.R; 26 | import org.cyanogenmod.designertools.overlays.GridOverlay; 27 | import org.cyanogenmod.designertools.overlays.MockOverlay; 28 | import org.cyanogenmod.designertools.utils.LaunchUtils; 29 | import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; 30 | import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; 31 | 32 | public class StartOverlayActivity extends Activity { 33 | private static final int REQUEST_OVERLAY_PERMISSION = StartOverlayActivity.class.hashCode(); 34 | 35 | public static final String EXTRA_OVERLAY_TYPE = "overlayType"; 36 | public static final int GRID_OVERLAY = 0; 37 | public static final int MOCK_OVERLAY = 1; 38 | public static final int COLOR_PICKER_OVERLAY = 2; 39 | 40 | private int mOverlayType = -1; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | Intent intent = getIntent(); 46 | if (intent.hasExtra(EXTRA_OVERLAY_TYPE)) { 47 | mOverlayType = intent.getIntExtra(EXTRA_OVERLAY_TYPE, -1); 48 | if (Settings.canDrawOverlays(this)) { 49 | startOverlayService(mOverlayType); 50 | finish(); 51 | } else { 52 | showReasoningDialog(); 53 | } 54 | } else { 55 | finish(); 56 | } 57 | } 58 | 59 | @Override 60 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 61 | if (requestCode == REQUEST_OVERLAY_PERMISSION) { 62 | if (Settings.canDrawOverlays(this)) { 63 | startOverlayService(mOverlayType); 64 | } 65 | finish(); 66 | } 67 | super.onActivityResult(requestCode, resultCode, data); 68 | } 69 | 70 | private void startOverlayService(int overlayType) { 71 | switch (overlayType) { 72 | case GRID_OVERLAY: 73 | Intent newIntent = new Intent(this, GridOverlay.class); 74 | this.startService(newIntent); 75 | GridPreferences.setGridOverlayActive(this, true); 76 | GridPreferences.setGridQsTileEnabled(this, true); 77 | break; 78 | case MOCK_OVERLAY: 79 | newIntent = new Intent(this, MockOverlay.class); 80 | this.startService(newIntent); 81 | MockPreferences.setMockOverlayActive(this, true); 82 | MockPreferences.setMockQsTileEnabled(this, true); 83 | break; 84 | case COLOR_PICKER_OVERLAY: 85 | LaunchUtils.startColorPickerOrRequestPermission(this); 86 | break; 87 | } 88 | } 89 | 90 | private void requestOverlayPermission() { 91 | Intent newIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 92 | Uri.parse("package:" + getPackageName())); 93 | startActivityForResult(newIntent, REQUEST_OVERLAY_PERMISSION); 94 | } 95 | 96 | private void showReasoningDialog() { 97 | AlertDialog.Builder builder = 98 | new AlertDialog.Builder(this, R.style.AlertDialog); 99 | builder.setTitle(R.string.dialog_request_overlay_permission_title) 100 | .setMessage(R.string.dialog_request_overlay_permission_message) 101 | .setPositiveButton(R.string.dialog_request_overlay_permission_grant, (dialog, which) -> { 102 | requestOverlayPermission(); 103 | }) 104 | .setNegativeButton(R.string.dialog_request_overlay_permission_deny, (dialog, which) -> { 105 | finish(); 106 | }) 107 | .setIcon(R.drawable.ic_launcher) 108 | .show(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/ColorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.content.Context; 19 | 20 | import org.cyanogenmod.designertools.R; 21 | 22 | public class ColorUtils { 23 | public static int getGridLineColor(Context context) { 24 | return PreferenceUtils.GridPreferences.getGridLineColor(context, 25 | context.getColor(R.color.dualColorPickerDefaultPrimaryColor)); 26 | } 27 | 28 | public static int getKeylineColor(Context context) { 29 | return PreferenceUtils.GridPreferences.getKeylineColor(context, 30 | context.getColor(R.color.dualColorPickerDefaultSecondaryColor)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/ImageUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.content.ContentResolver; 19 | import android.content.Context; 20 | import android.graphics.Bitmap; 21 | import android.graphics.BitmapFactory; 22 | import android.net.Uri; 23 | import android.util.Log; 24 | 25 | import java.io.FileNotFoundException; 26 | import java.io.FileOutputStream; 27 | import java.io.IOException; 28 | import java.io.InputStream; 29 | 30 | public class ImageUtils { 31 | private static final String TAG = ImageUtils.class.getSimpleName(); 32 | 33 | public static Bitmap getBitmapFromUri(Context context, Uri uri) { 34 | String scheme = uri.getScheme(); 35 | Bitmap image = null; 36 | if (ContentResolver.SCHEME_CONTENT.equals(scheme) 37 | || ContentResolver.SCHEME_FILE.equals(scheme)) { 38 | InputStream stream = null; 39 | try { 40 | stream = context.getContentResolver().openInputStream(uri); 41 | image = BitmapFactory.decodeStream(stream); 42 | } catch (Exception e) { 43 | Log.w(TAG, "Unable to open content: " + uri, e); 44 | } finally { 45 | if (stream != null) { 46 | try { 47 | stream.close(); 48 | } catch (IOException e) { 49 | Log.w(TAG, "Unable to close content: " + uri, e); 50 | } 51 | } 52 | } 53 | } 54 | 55 | return image; 56 | } 57 | 58 | public static boolean saveBitmap(Bitmap bmp, String path) throws FileNotFoundException { 59 | if (bmp == null || path == null) return false; 60 | 61 | FileOutputStream outputStream = new FileOutputStream(path); 62 | return bmp.compress(Bitmap.CompressFormat.PNG, 80, outputStream); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/LaunchUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.app.Activity; 19 | import android.content.Context; 20 | import android.content.Intent; 21 | 22 | import org.cyanogenmod.designertools.DesignerToolsApplication; 23 | import org.cyanogenmod.designertools.overlays.ColorPickerOverlay; 24 | import org.cyanogenmod.designertools.overlays.GridOverlay; 25 | import org.cyanogenmod.designertools.overlays.MockOverlay; 26 | import org.cyanogenmod.designertools.ui.ScreenRecordRequestActivity; 27 | import org.cyanogenmod.designertools.ui.StartOverlayActivity; 28 | import org.cyanogenmod.designertools.utils.PreferenceUtils.ColorPickerPreferences; 29 | import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; 30 | import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; 31 | 32 | public class LaunchUtils { 33 | public static void launchGridOverlay(Context context) { 34 | startOverlayActivity(context, StartOverlayActivity.GRID_OVERLAY); 35 | } 36 | 37 | public static void cancelGridOverlay(Context context) { 38 | Intent newIntent = new Intent(context, GridOverlay.class); 39 | context.stopService(newIntent); 40 | GridPreferences.setGridOverlayActive(context, false); 41 | GridPreferences.setGridQsTileEnabled(context, false); 42 | } 43 | 44 | public static void launchMockOverlay(Context context) { 45 | startOverlayActivity(context, StartOverlayActivity.MOCK_OVERLAY); 46 | } 47 | 48 | public static void cancelMockOverlay(Context context) { 49 | Intent newIntent = new Intent(context, MockOverlay.class); 50 | context.stopService(newIntent); 51 | MockPreferences.setMockOverlayActive(context, false); 52 | MockPreferences.setMockQsTileEnabled(context, false); 53 | } 54 | 55 | public static void launchColorPickerOverlay(Context context) { 56 | startOverlayActivity(context, StartOverlayActivity.COLOR_PICKER_OVERLAY); 57 | } 58 | 59 | public static void cancelColorPickerOverlay(Context context) { 60 | Intent newIntent = new Intent(context, ColorPickerOverlay.class); 61 | context.stopService(newIntent); 62 | ColorPickerPreferences.setColorPickerActive(context, false); 63 | ColorPickerPreferences.setColorPickerQsTileEnabled(context, false); 64 | } 65 | 66 | public static void startColorPickerOrRequestPermission(Context context) { 67 | DesignerToolsApplication app = 68 | (DesignerToolsApplication) context.getApplicationContext(); 69 | if (app.getScreenRecordResultCode() == Activity.RESULT_OK && app.getScreenRecordResultData() != null) { 70 | Intent newIntent = new Intent(context, ColorPickerOverlay.class); 71 | context.startService(newIntent); 72 | ColorPickerPreferences.setColorPickerActive(context, true); 73 | ColorPickerPreferences.setColorPickerQsTileEnabled(context, true); 74 | } else { 75 | Intent intent = new Intent(context, ScreenRecordRequestActivity.class); 76 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 77 | context.startActivity(intent); 78 | } 79 | } 80 | 81 | private static void startOverlayActivity(Context context, int overlayType) { 82 | Intent intent = new Intent(context, StartOverlayActivity.class); 83 | intent.putExtra(StartOverlayActivity.EXTRA_OVERLAY_TYPE, overlayType); 84 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 85 | context.startActivity(intent); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/LayoutRenderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.graphics.Bitmap; 19 | import android.graphics.Canvas; 20 | import android.view.View; 21 | import android.widget.FrameLayout; 22 | 23 | public class LayoutRenderUtils { 24 | 25 | public static Bitmap renderViewToBitmap(View view) { 26 | // Provide it with a layout params. It should necessarily be wrapping the 27 | // content as we not really going to have a parent for it. 28 | view.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, 29 | FrameLayout.LayoutParams.WRAP_CONTENT)); 30 | 31 | // Pre-measure the view so that height and width don't remain null. 32 | view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 33 | View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 34 | 35 | // Assign a size and position to the view and all of its descendants 36 | view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); 37 | 38 | // Create the bitmap 39 | Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), 40 | view.getMeasuredHeight(), 41 | Bitmap.Config.ARGB_8888); 42 | // Create a canvas with the specified bitmap to draw into 43 | Canvas c = new Canvas(bitmap); 44 | 45 | // Render this view to the given Canvas 46 | view.draw(c); 47 | return bitmap; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/MockupUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 The CyanogenMod Project 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.content.Context; 19 | import android.graphics.Bitmap; 20 | import android.graphics.BitmapFactory; 21 | 22 | import org.cyanogenmod.designertools.utils.PreferenceUtils.MockPreferences; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | 27 | public class MockupUtils { 28 | private static final String MOCKUP_DIRECTORY = "mockups"; 29 | 30 | public static final String PORTRAIT_MOCKUP_FILENAME = "mockup_portrait"; 31 | public static final String LANDSCAPE_MOCKUP_FILENAME = "mockup_landscape"; 32 | 33 | public static void savePortraitMockup(Context context, Bitmap bmp) throws IOException { 34 | saveMockup(context, bmp, PORTRAIT_MOCKUP_FILENAME); 35 | } 36 | 37 | public static Bitmap getPortraitMockup(Context context) { 38 | return loadMockup(context, PORTRAIT_MOCKUP_FILENAME); 39 | } 40 | 41 | public static void saveLandscapeMockup(Context context, Bitmap bmp) throws IOException { 42 | saveMockup(context, bmp, LANDSCAPE_MOCKUP_FILENAME); 43 | } 44 | 45 | public static Bitmap getLandscapeMockup(Context context) { 46 | return loadMockup(context, LANDSCAPE_MOCKUP_FILENAME); 47 | } 48 | 49 | private static void saveMockup(Context context, Bitmap bmp, String fileName) 50 | throws IOException { 51 | String path = context.getFilesDir().getAbsolutePath() + File.separator + MOCKUP_DIRECTORY; 52 | File dir = new File(path); 53 | if (!dir.exists()) { 54 | if (!dir.mkdirs()) { 55 | throw new IOException("Unable to mkdris"); 56 | } 57 | } 58 | String filePath = path + File.separator + fileName; 59 | if (bmp != null) { 60 | ImageUtils.saveBitmap(bmp, path + File.separator + fileName); 61 | if (PORTRAIT_MOCKUP_FILENAME.equals(fileName)) { 62 | MockPreferences.setPortraitMocupkOverlay(context, filePath); 63 | } else if (LANDSCAPE_MOCKUP_FILENAME.equals(fileName)) { 64 | MockPreferences.setLandscapeMocupkOverlay(context, filePath); 65 | } 66 | } else { 67 | if (PORTRAIT_MOCKUP_FILENAME.equals(fileName)) { 68 | if (new File(filePath).delete()) { 69 | MockPreferences.setPortraitMocupkOverlay(context, ""); 70 | } 71 | } else if (LANDSCAPE_MOCKUP_FILENAME.equals(fileName)) { 72 | if (new File(filePath).delete()) { 73 | MockPreferences.setLandscapeMocupkOverlay(context, ""); 74 | } 75 | } 76 | } 77 | } 78 | 79 | private static Bitmap loadMockup(Context context, String fileName) { 80 | File file = new File(context.getFilesDir().getAbsolutePath() + File.separator + 81 | MOCKUP_DIRECTORY + File.separator + fileName); 82 | if (!file.exists()) return null; 83 | 84 | return BitmapFactory.decodeFile(file.getAbsolutePath()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/NotificationUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Scheff's Blend 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.app.Notification; 19 | import android.app.NotificationChannel; 20 | import android.app.NotificationManager; 21 | import android.app.PendingIntent; 22 | import android.content.Context; 23 | import android.os.Build; 24 | import androidx.annotation.DrawableRes; 25 | import androidx.annotation.NonNull; 26 | import androidx.core.app.NotificationCompat; 27 | 28 | public class NotificationUtils { 29 | @NonNull 30 | public static Notification createForegroundServiceNotification( 31 | @NonNull Context context, 32 | @NonNull String channelId, 33 | @DrawableRes int icon, 34 | @NonNull String title, 35 | @NonNull String contentText, 36 | @NonNull PendingIntent contentIntent) { 37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 38 | NotificationManager nm = context.getSystemService(NotificationManager.class); 39 | NotificationChannel channel = nm.getNotificationChannel(channelId); 40 | if (channel == null) { 41 | channel = new NotificationChannel(channelId, channelId, 42 | NotificationManager.IMPORTANCE_NONE); 43 | channel.enableLights(false); 44 | nm.createNotificationChannel(channel); 45 | } 46 | } 47 | 48 | NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId); 49 | builder.setPriority(Notification.PRIORITY_MIN) 50 | .setSmallIcon(icon) 51 | .setContentTitle(title) 52 | .setContentText(contentText) 53 | .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText)) 54 | .setContentIntent(contentIntent); 55 | 56 | return builder.build(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/utils/ViewUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Scheff's Blend 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 | package org.cyanogenmod.designertools.utils; 17 | 18 | import android.os.Build; 19 | import android.view.WindowManager; 20 | 21 | public class ViewUtils { 22 | 23 | public static int getWindowType() { 24 | return getWindowType(false); 25 | } 26 | 27 | public static int getWindowType(boolean useSystemAlert) { 28 | return (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) 29 | ? (useSystemAlert 30 | ? WindowManager.LayoutParams.TYPE_SYSTEM_ALERT 31 | : WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY) 32 | : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/widget/DualColorPicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Cyanogen, Inc. 3 | */ 4 | package org.cyanogenmod.designertools.widget; 5 | 6 | import android.content.Context; 7 | import android.content.res.TypedArray; 8 | import android.graphics.Canvas; 9 | import android.graphics.Color; 10 | import android.graphics.Paint; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | 14 | import org.cyanogenmod.designertools.R; 15 | import org.cyanogenmod.designertools.utils.PreferenceUtils.GridPreferences; 16 | 17 | public class DualColorPicker extends View { 18 | private static final float STROKE_WIDTH = 5f; 19 | private static final float COLOR_DARKEN_FACTOR = 0.8f; 20 | 21 | private Paint mPrimaryFillPaint; 22 | private Paint mSecondaryFillPaint; 23 | private Paint mPrimaryStrokePaint; 24 | private Paint mSecondaryStrokePaint; 25 | 26 | public DualColorPicker(Context context) { 27 | this(context, null); 28 | } 29 | 30 | public DualColorPicker(Context context, AttributeSet attrs) { 31 | this(context, attrs, 0); 32 | } 33 | 34 | public DualColorPicker(Context context, AttributeSet attrs, int defStyleAttr) { 35 | this(context, attrs, defStyleAttr, 0); 36 | } 37 | 38 | public DualColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 39 | super(context, attrs, defStyleAttr, defStyleRes); 40 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DualColorPicker, 0, 0); 41 | int primaryColor = ta.getColor(R.styleable.DualColorPicker_primaryColor, 42 | GridPreferences.getGridLineColor(context, 43 | context.getColor(R.color.dualColorPickerDefaultPrimaryColor))); 44 | int secondaryColor = ta.getColor(R.styleable.DualColorPicker_primaryColor, 45 | GridPreferences.getKeylineColor(context, 46 | context.getColor(R.color.dualColorPickerDefaultSecondaryColor))); 47 | 48 | mPrimaryFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); 49 | mPrimaryFillPaint.setStyle(Paint.Style.FILL); 50 | mPrimaryFillPaint.setColor(primaryColor); 51 | mPrimaryStrokePaint = new Paint(mPrimaryFillPaint); 52 | mPrimaryStrokePaint.setStyle(Paint.Style.STROKE); 53 | mPrimaryStrokePaint.setStrokeWidth(STROKE_WIDTH); 54 | mPrimaryStrokePaint.setColor(getDarkenedColor(primaryColor)); 55 | 56 | mSecondaryFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); 57 | mSecondaryFillPaint.setStyle(Paint.Style.FILL_AND_STROKE); 58 | mSecondaryFillPaint.setColor(secondaryColor); 59 | mSecondaryStrokePaint = new Paint(mSecondaryFillPaint); 60 | mSecondaryStrokePaint.setStyle(Paint.Style.STROKE); 61 | mSecondaryStrokePaint.setStrokeWidth(STROKE_WIDTH); 62 | mSecondaryStrokePaint.setColor(getDarkenedColor(secondaryColor)); 63 | } 64 | 65 | @Override 66 | protected void onDraw(Canvas canvas) { 67 | final float width = getWidth(); 68 | final float height = getHeight(); 69 | final float widthDiv2 = width / 2f; 70 | final float heightDiv2 = height / 2f; 71 | final float radius = Math.min(widthDiv2, heightDiv2) * 0.9f; 72 | 73 | // erase everything 74 | canvas.drawColor(0); 75 | 76 | // draw the left half 77 | canvas.save(); 78 | canvas.clipRect(0, 0, widthDiv2, height); 79 | canvas.drawCircle(widthDiv2, heightDiv2, radius, mPrimaryFillPaint); 80 | canvas.drawCircle(widthDiv2, heightDiv2, radius, mPrimaryStrokePaint); 81 | canvas.drawLine(widthDiv2 - STROKE_WIDTH / 2f, heightDiv2 - radius, 82 | widthDiv2 - STROKE_WIDTH / 2f, heightDiv2 + radius, mPrimaryStrokePaint); 83 | canvas.restore(); 84 | 85 | /// draw the right half 86 | canvas.save(); 87 | canvas.clipRect(widthDiv2, 0, width, height); 88 | canvas.drawCircle(widthDiv2, heightDiv2, radius, mSecondaryFillPaint); 89 | canvas.drawCircle(widthDiv2, heightDiv2, radius, mSecondaryStrokePaint); 90 | canvas.drawLine(widthDiv2 + STROKE_WIDTH / 2f, heightDiv2 - radius, 91 | widthDiv2 + STROKE_WIDTH / 2f, heightDiv2 + radius, mSecondaryStrokePaint); 92 | canvas.restore(); 93 | } 94 | 95 | private int getDarkenedColor(int color) { 96 | int a = Color.alpha(color); 97 | int r = (int) (Color.red(color) * COLOR_DARKEN_FACTOR); 98 | int g = (int) (Color.green(color) * COLOR_DARKEN_FACTOR); 99 | int b = (int) (Color.blue(color) * COLOR_DARKEN_FACTOR); 100 | 101 | return Color.argb(a, r, g, b); 102 | } 103 | 104 | public void setPrimaryColor(int color) { 105 | mPrimaryFillPaint.setColor(color); 106 | mPrimaryStrokePaint.setColor(getDarkenedColor(color)); 107 | invalidate(); 108 | } 109 | 110 | public int getPrimaryColor() { 111 | return mPrimaryFillPaint.getColor(); 112 | } 113 | 114 | public void setSecondaryColor(int color) { 115 | mSecondaryFillPaint.setColor(color); 116 | mSecondaryStrokePaint.setColor(getDarkenedColor(color)); 117 | invalidate(); 118 | } 119 | 120 | public int getSecondaryColor() { 121 | return mSecondaryFillPaint.getColor(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/widget/GridPreview.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Cyanogen, Inc. 3 | */ 4 | package org.cyanogenmod.designertools.widget; 5 | 6 | import android.content.Context; 7 | import android.graphics.Canvas; 8 | import android.graphics.Paint; 9 | import android.graphics.Rect; 10 | import android.util.AttributeSet; 11 | import android.view.View; 12 | 13 | import org.cyanogenmod.designertools.R; 14 | 15 | public class GridPreview extends View { 16 | // default line width in dp 17 | private static final float DEFAULT_LINE_WIDTH = 1f; 18 | // default column size in dp 19 | private static final int DEFAULT_COLUMN_SIZE = 8; 20 | // default row size in dp 21 | private static final int DEFAULT_ROW_SIZE = 8; 22 | private static final int BACKGROUND_COLOR = 0x1f000000; 23 | 24 | private float mGridLineWidth; 25 | private float mColumnSize; 26 | private float mRowSize; 27 | private float mDensity; 28 | private int mColumnSizeDp; 29 | private int mRowSizeDp; 30 | 31 | private Paint mGridLinePaint; 32 | private Paint mGridSizeTextPaint; 33 | 34 | public GridPreview(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public GridPreview(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public GridPreview(Context context, AttributeSet attrs, int defStyleAttr) { 43 | this(context, attrs, defStyleAttr, 0); 44 | } 45 | 46 | public GridPreview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 47 | super(context, attrs, defStyleAttr, defStyleRes); 48 | 49 | mDensity = getResources().getDisplayMetrics().density; 50 | 51 | mGridLineWidth = DEFAULT_LINE_WIDTH * mDensity; 52 | mColumnSizeDp = DEFAULT_COLUMN_SIZE; 53 | mColumnSize = mColumnSizeDp * mDensity; 54 | mRowSizeDp = DEFAULT_ROW_SIZE; 55 | mRowSize = mRowSizeDp * mDensity; 56 | 57 | mGridLinePaint = new Paint(); 58 | mGridLinePaint.setColor(context.getColor(R.color.colorGridOverlayCardTint)); 59 | mGridLinePaint.setStrokeWidth(mGridLineWidth); 60 | 61 | mGridSizeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); 62 | mGridSizeTextPaint.setTextSize( 63 | getResources().getDimensionPixelSize(R.dimen.grid_preview_text_size)); 64 | mGridSizeTextPaint.setColor(BACKGROUND_COLOR); 65 | } 66 | 67 | @Override 68 | protected void onDraw(Canvas canvas) { 69 | float width = getWidth(); 70 | float height = getHeight(); 71 | 72 | canvas.drawColor(BACKGROUND_COLOR); 73 | for (float x = mColumnSize; x < width; x += mColumnSize) { 74 | canvas.drawLine(x, 0, x, height, mGridLinePaint); 75 | } 76 | for (float y = mRowSize; y < height; y += mRowSize) { 77 | canvas.drawLine(0, y, width, y, mGridLinePaint); 78 | } 79 | 80 | String text = String.format("%d x %d", mColumnSizeDp, mRowSizeDp); 81 | Rect bounds = new Rect(); 82 | mGridSizeTextPaint.getTextBounds(text, 0, text.length(), bounds); 83 | canvas.drawText(text, (width - bounds.width()) / 2f, (height + bounds.height()) / 2f, mGridSizeTextPaint); 84 | } 85 | 86 | public void setColumnSize(int columnSize) { 87 | mColumnSizeDp = columnSize; 88 | mColumnSize = mColumnSizeDp * mDensity; 89 | invalidate(); 90 | } 91 | 92 | public int getColumnSize() { 93 | return mColumnSizeDp; 94 | } 95 | 96 | public void setRowSize(int rowSize) { 97 | mRowSizeDp = rowSize; 98 | mRowSize = mRowSizeDp * mDensity; 99 | invalidate(); 100 | } 101 | 102 | public int getRowSize() { 103 | return mRowSizeDp; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/widget/MagnifierNodeView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Cyanogen, Inc. 3 | */ 4 | package org.cyanogenmod.designertools.widget; 5 | 6 | import android.content.Context; 7 | import android.graphics.Canvas; 8 | import android.graphics.Paint; 9 | import android.graphics.PorterDuff; 10 | import android.graphics.PorterDuffXfermode; 11 | import android.util.AttributeSet; 12 | import android.util.DisplayMetrics; 13 | import android.view.View; 14 | 15 | import org.cyanogenmod.designertools.R; 16 | 17 | public class MagnifierNodeView extends View { 18 | private Paint mReticlePaint; 19 | private Paint mOutlinePaint; 20 | private Paint mFillPaint; 21 | private Paint mClearPaint; 22 | 23 | private float mCenterX; 24 | private float mCenterY; 25 | private float mRadius; 26 | private float mReticleRadius; 27 | private float mDensity; 28 | 29 | public MagnifierNodeView(Context context) { 30 | this(context, null); 31 | } 32 | 33 | public MagnifierNodeView(Context context, AttributeSet attrs) { 34 | this(context, attrs, 0); 35 | } 36 | 37 | public MagnifierNodeView(Context context, AttributeSet attrs, int defStyleAttr) { 38 | this(context, attrs, defStyleAttr, 0); 39 | } 40 | 41 | public MagnifierNodeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 42 | super(context, attrs, defStyleAttr, defStyleRes); 43 | DisplayMetrics dm = getResources().getDisplayMetrics(); 44 | float twoDp = 2f * dm.density; 45 | mReticlePaint = new Paint(); 46 | mReticlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 47 | mReticlePaint.setColor(context.getColor(R.color.colorPickerNodeReticleColor)); 48 | mReticlePaint.setStrokeWidth(twoDp); 49 | mReticlePaint.setStyle(Paint.Style.STROKE); 50 | 51 | mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 52 | mOutlinePaint.setColor(context.getColor(R.color.colorPickerNodeOutlineColor)); 53 | mOutlinePaint.setStrokeWidth(twoDp); 54 | mOutlinePaint.setStyle(Paint.Style.STROKE); 55 | mOutlinePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); 56 | 57 | mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 58 | mFillPaint.setColor(context.getColor(R.color.colorPickerNodeFillColor)); 59 | mFillPaint.setStrokeWidth(twoDp); 60 | mFillPaint.setStyle(Paint.Style.FILL_AND_STROKE); 61 | mFillPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); 62 | 63 | mClearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 64 | mClearPaint.setColor(context.getColor(R.color.colorPickerNodeClearColor)); 65 | mClearPaint.setStrokeWidth(twoDp); 66 | mClearPaint.setStyle(Paint.Style.FILL); 67 | mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 68 | 69 | mReticleRadius = getResources().getInteger(R.integer.color_picker_sample_width) / 2 + twoDp; 70 | mDensity = dm.density; 71 | } 72 | 73 | @Override 74 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 75 | super.onSizeChanged(w, h, oldw, oldh); 76 | mRadius = Math.min(w, h) / 2.0f - mDensity * 2f; 77 | mCenterX = w / 2.0f; 78 | mCenterY = h / 2.0f; 79 | } 80 | 81 | @Override 82 | protected void onDraw(Canvas canvas) { 83 | canvas.drawCircle(mCenterX, mCenterY, mRadius, mFillPaint); 84 | canvas.drawCircle(mCenterX, mCenterY, mRadius, mOutlinePaint); 85 | canvas.drawCircle(mCenterX, mCenterY, mReticleRadius, mClearPaint); 86 | canvas.drawCircle(mCenterX, mCenterY, mReticleRadius, mReticlePaint); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/org/cyanogenmod/designertools/widget/VerticalSeekBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Cyanogen, Inc. 3 | */ 4 | package org.cyanogenmod.designertools.widget; 5 | 6 | import android.annotation.SuppressLint; 7 | import android.content.Context; 8 | import android.graphics.Canvas; 9 | import android.graphics.Rect; 10 | import android.graphics.drawable.Drawable; 11 | import android.os.Build; 12 | import android.util.AttributeSet; 13 | import android.view.MotionEvent; 14 | import android.widget.SeekBar; 15 | 16 | @SuppressLint("AppCompatCustomView") 17 | public class VerticalSeekBar extends SeekBar { 18 | 19 | public VerticalSeekBar(Context context) { 20 | super(context); 21 | } 22 | 23 | public VerticalSeekBar(Context context, AttributeSet attrs) { 24 | super(context, attrs); 25 | } 26 | 27 | public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { 28 | super(context, attrs, defStyle); 29 | } 30 | 31 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 32 | super.onSizeChanged(h, w, oldh, oldw); 33 | } 34 | 35 | @Override 36 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 37 | super.onMeasure(heightMeasureSpec, widthMeasureSpec); 38 | setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); 39 | } 40 | 41 | protected void onDraw(Canvas c) { 42 | c.rotate(270); 43 | c.translate(-getHeight(), 0); 44 | super.onDraw(c); 45 | 46 | // Work around for known bug with Marshmallow where the enabled thumb is not drawn 47 | if (isEnabled() && Build.VERSION.SDK_INT == Build.VERSION_CODES.M) { 48 | drawThumb(c); 49 | } 50 | } 51 | 52 | void drawThumb(Canvas canvas) { 53 | Drawable thumb = getThumb(); 54 | if (thumb != null) { 55 | Rect thumbBounds = thumb.getBounds(); 56 | canvas.save(); 57 | canvas.rotate(270, thumbBounds.exactCenterX(), thumbBounds.exactCenterY()); 58 | canvas.translate(0, thumbBounds.height() / 3f); 59 | thumb.draw(canvas); 60 | canvas.restore(); 61 | } 62 | } 63 | 64 | @Override 65 | public boolean onTouchEvent(MotionEvent event) { 66 | if (!isEnabled()) { 67 | return false; 68 | } 69 | 70 | switch (event.getAction()) { 71 | case MotionEvent.ACTION_DOWN: 72 | case MotionEvent.ACTION_MOVE: 73 | case MotionEvent.ACTION_UP: 74 | setProgress(getMax() - (int) (getMax() * event.getY() / getHeight())); 75 | onSizeChanged(getWidth(), getHeight(), 0, 0); 76 | break; 77 | 78 | case MotionEvent.ACTION_CANCEL: 79 | break; 80 | } 81 | return true; 82 | } 83 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/color_hex_backer.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-hdpi/color_hex_backer.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_header_glyph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-hdpi/ic_header_glyph.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/loop_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-hdpi/loop_ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/color_hex_backer.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-mdpi/color_hex_backer.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_header_glyph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-mdpi/ic_header_glyph.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/loop_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-mdpi/loop_ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/aaron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-nodpi/aaron.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/asher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-nodpi/asher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/clark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-nodpi/clark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/img_header_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-nodpi/img_header_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/kover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-nodpi/kover.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/color_hex_backer.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xhdpi/color_hex_backer.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_header_glyph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xhdpi/ic_header_glyph.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/loop_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xhdpi/loop_ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/color_hex_backer.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxhdpi/color_hex_backer.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_header_glyph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxhdpi/ic_header_glyph.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/loop_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxhdpi/loop_ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/color_hex_backer.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxxhdpi/color_hex_backer.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/loop_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xD34D/DesignerTools/0c88d6b2ca894560f2dea357b06f72166584c0b5/app/src/main/res/drawable-xxxhdpi/loop_ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/half_circle_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 26 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_header_glyph.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_marker_horiz_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_marker_horiz_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_marker_vert.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_colorpicker_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_colorpicker_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_grid_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_grid_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_layoutbounds_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_layoutbounds_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_overlay_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_overlay_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_screenshotinfo_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qs_screenshotinfo_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shortcut_colorpicker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shortcut_grid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shortcut_mock.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/loop_node.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pick_mock_overlay_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pick_mockup_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | 25 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/activity_designer_tools.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 37 | 38 | 42 | 43 | 50 | 51 | 57 | 58 | 66 | 67 | 75 | 76 | 77 | 78 | 85 | 86 | 92 | 93 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/app_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 20 | 21 | 26 | 27 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout-w600dp/activity_designer_tools.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 37 | 38 | 42 | 43 | 50 | 51 | 57 | 58 | 66 | 67 | 75 | 76 | 77 | 78 | 85 | 86 | 92 | 93 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_credits.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 25 | 26 | 27 | 28 | 35 | 36 | 40 | 46 | 55 | 60 | 64 | 65 | 66 | 67 | 72 | 78 | 87 | 92 | 96 | 97 | 98 | 99 | 104 | 110 | 119 | 124 | 128 | 129 | 130 | 131 | 136 | 142 | 151 | 156 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_designer_tools.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 36 | 37 | 45 | 46 | 52 | 53 | 60 | 61 | 68 | 69 | 77 | 78 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 27 | 28 | 35 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 26 | 27 | 32 | 33 | 42 | 43 | 47 | 48 | 49 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 30 | 31 | 32 | 33 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/color_picker_magnifier.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/credits_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 27 | 28 | 35 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_color_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 26 | 27 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/grid_overlay_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 25 | 26 | 34 | 35 | 39 | 40 | 41 | 42 | 45 | 46 | 54 | 55 | 60 | 61 | 62 | 63 | 66 | 67 | 75 | 76 | 81 | 82 | 83 | 84 | 88 | 89 | 96 | 97 | 102 | 103 | 108 | 109 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /app/src/main/res/layout/lobsterpicker.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 22 | 23 | 29 | 30 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/mockup_overlay_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 21 | 22 | 29 | 30 | 34 | 35 | 39 | 40 | 48 | 49 | 55 | 56 | 57 | 58 | 62 | 63 | 73 | 74 | 82 | 83 |