1 /* <lambda>null2 * Copyright 2021 The Android Open Source 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 17 package androidx.glance.appwidget.layoutgenerator.gradle 18 19 import androidx.glance.appwidget.layoutgenerator.GeneratedFiles 20 import androidx.glance.appwidget.layoutgenerator.LayoutGenerator 21 import androidx.glance.appwidget.layoutgenerator.cleanResources 22 import androidx.glance.appwidget.layoutgenerator.generateRegistry 23 import com.android.build.api.variant.AndroidComponentsExtension 24 import java.io.File 25 import org.gradle.api.DefaultTask 26 import org.gradle.api.Project 27 import org.gradle.api.file.DirectoryProperty 28 import org.gradle.api.tasks.CacheableTask 29 import org.gradle.api.tasks.InputDirectory 30 import org.gradle.api.tasks.OutputDirectory 31 import org.gradle.api.tasks.PathSensitive 32 import org.gradle.api.tasks.PathSensitivity 33 import org.gradle.api.tasks.TaskAction 34 35 /** 36 * Task generating the layouts from a set of Layout templates. 37 * 38 * See [LayoutGenerator] for details on the template format, and [generateRegistry] for details on 39 * the Kotlin code generated to access those layouts from code. 40 */ 41 @CacheableTask 42 abstract class LayoutGeneratorTask : DefaultTask() { 43 44 @get:PathSensitive(PathSensitivity.NAME_ONLY) 45 @get:InputDirectory 46 abstract val containerLayoutDirectory: DirectoryProperty 47 48 @get:PathSensitive(PathSensitivity.NAME_ONLY) 49 @get:InputDirectory 50 abstract val childLayoutDirectory: DirectoryProperty 51 52 @get:OutputDirectory abstract val outputSourceDir: DirectoryProperty 53 54 @get:OutputDirectory abstract val outputResourcesDir: DirectoryProperty 55 56 @TaskAction 57 fun execute() { 58 59 outputSourceDir.asFile.get().mkdirs() 60 outputResourcesDir.asFile.get().mkdirs() 61 62 val generatedLayouts = 63 LayoutGenerator() 64 .generateAllFiles( 65 checkNotNull(containerLayoutDirectory.get().asFile.listFiles()).asList(), 66 checkNotNull(childLayoutDirectory.get().asFile.listFiles()).asList(), 67 outputResourcesDir.get().asFile 68 ) 69 generateRegistry( 70 packageName = outputModule, 71 layouts = generatedLayouts.generatedContainers, 72 boxChildLayouts = generatedLayouts.generatedBoxChildren, 73 rowColumnChildLayouts = generatedLayouts.generatedRowColumnChildren, 74 outputSourceDir = outputSourceDir.get().asFile 75 ) 76 cleanResources(outputResourcesDir.get().asFile, generatedLayouts.extractGeneratedFiles()) 77 } 78 79 private fun GeneratedFiles.extractGeneratedFiles(): Set<File> = 80 generatedContainers.values 81 .flatMap { container -> container.map { it.generatedFile } } 82 .toSet() + 83 generatedBoxChildren.values 84 .flatMap { child -> child.map { it.generatedFile } } 85 .toSet() + 86 generatedRowColumnChildren.values 87 .flatMap { child -> child.map { it.generatedFile } } 88 .toSet() + 89 extraFiles 90 91 companion object { 92 /** Registers [LayoutGeneratorTask] in [project] for all variants. */ 93 @JvmStatic 94 fun registerLayoutGenerator( 95 project: Project, 96 containerLayoutDirectory: File, 97 childLayoutDirectory: File, 98 ) { 99 100 val outputDirectory = "generatedLayouts" 101 val buildDirectory = project.layout.buildDirectory 102 103 val taskName = "generateLayouts" 104 105 val task = 106 project.tasks.register(taskName, LayoutGeneratorTask::class.java) { 107 it.containerLayoutDirectory.set(containerLayoutDirectory) 108 it.childLayoutDirectory.set(childLayoutDirectory) 109 it.outputSourceDir.set(buildDirectory.dir("$outputDirectory/kotlin")) 110 it.outputResourcesDir.set(buildDirectory.dir("$outputDirectory/res/layouts")) 111 } 112 113 project.extensions.getByType(AndroidComponentsExtension::class.java).onVariants { 114 variant -> 115 variant.sources.java?.addGeneratedSourceDirectory( 116 task, 117 LayoutGeneratorTask::outputSourceDir 118 ) 119 variant.sources.res?.addGeneratedSourceDirectory( 120 task, 121 LayoutGeneratorTask::outputResourcesDir 122 ) 123 } 124 } 125 } 126 } 127 128 private const val outputModule: String = "androidx.glance.appwidget" 129