summaryrefslogtreecommitdiff
path: root/wizard/template-plugin/src/com/android/tools/idea/wizard/template/Template.kt
blob: f522916abcd4412febad6019146696c96c546cf6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package com.android.tools.idea.wizard.template

typealias Recipe = RecipeExecutor.(TemplateData) -> Unit

/**
 * Determines in which context (basically a screen) the template should be shown.
 * Note: [NewProjectExtraDetail] should only be used if [NewProject] is simultaneously used.
 */
enum class WizardUiContext {
  NewProject,
  /** Show extra step for Activity details in New Project. */
  NewProjectExtraDetail,
  NewModule,
  MenuEntry,
  ActivityGallery,
  FragmentGallery
}

/**
 * Determines to which menu entry the template belongs.
 */
enum class Category {
  Activity,
  Fragment,
  Application,
  Folder,
  Service,
  UiComponent,
  Automotive,
  XML,
  Wear,
  AIDL,
  Widget,
  Google,
  Compose,
  Other,
}

/**
 * Representations of all Android hardware devices we can target when building an app.
 */
enum class FormFactor(val displayName: String) {
  Mobile("Phone and Tablet"),
  Wear("Wear OS"),
  Tv("Android TV"),
  Automotive("Automotive"),
  Generic("Generic");

  override fun toString(): String {
    return displayName
  }
}

enum class TemplateConstraint {
  AndroidX,
  Kotlin,
  Material3,
  // Compose is used as a Constraint since it implies the need of a specific Kotlin Compiler version
  Compose,
  Aidl
}

/**
 * Describes a template available in the wizard.
 *
 * This interface is used by the wizard in 3 steps:
 * 1. User is presented an option to select a template, for example when creating a new Module, browsing activity gallery,
 * or choosing from the New -> X menu. Selection of the Template depends on fields like [Category], [FormFactor], etc.
 * 2. After the user selects a template, the wizards will call [Parameter]s to build the UI.
 * 3. Recipe is executed with parameters' values supplied by the user in the UI.
 **/
interface Template {
  /**
   * A template name which is also used as identified.
   */
  val name: String
  /**
   * A textual description which is shown in wizards UIs.
   */
  val description: String
  /**
   * Address of an external website with more details about the template.
   */
  val documentationUrl: String?
  /** Returns a thumbnail which are drawn in the UI. It will be called every time when any parameter is updated. */
  // TODO(qumeric): consider using IconLoader and/or wizard icons.
  fun thumb(): Thumb

  /**
   * When a [Template] is chosen by the user, the [widgets] are used by the Wizards to build the user UI.
   *
   * Usually, it displays an input for [Parameter].
   */
  val widgets: Collection<Widget<*>>
  /**
   * Usually, a user provides [Parameter.value]s by interaction with the UI [widgets].
   */
  val parameters: Collection<Parameter<*>> get() = widgets.filterIsInstance<ParameterWidget<*>>().map { it.parameter }

  /**
   * Recipe used to generate this [Template] output. It will be called after the user provides values for all [Parameter]s.
   */
  val recipe: Recipe

  /** The template will be shown only in given context. Should include all possible contexts by default. */
  val uiContexts: Collection<WizardUiContext>
  /**
   * Minimum sdk version required to build this template.
   * If minSdkVersion in build.gradle is less than [minSdk], the template will not be available (e.g. action will be disabled).
   */
  val minSdk: Int
  /**
   * Determines to which menu entry the template belongs.
   */
  val category: Category
  /**
   * Determines to which form factor the template belongs. Templates with particular form factor may only be rendered in the
   * project of corresponding [Category].
   */
  val formFactor: FormFactor
  /** Conditions under which the template may be rendered. For example, some templates only support AndroidX */
  val constraints: Collection<TemplateConstraint>

  val useGenericInstrumentedTests: Boolean

  val useGenericLocalTests: Boolean

  /**
   * Represent absence of a [Template] (null object pattern).
   */
  companion object NoActivity: Template {
    override val widgets: Collection<Widget<*>> = listOf()
    override val uiContexts: Collection<WizardUiContext> get() = listOf(WizardUiContext.ActivityGallery)
    override val constraints: Collection<TemplateConstraint> = listOf()
    override val recipe: Recipe get() = throw UnsupportedOperationException()
    override val name: String = "No Activity"
    override val description: String = "Creates a new empty project"
    override val documentationUrl: String? = null
    override val minSdk: Int = 1
    override val category: Category = Category.Activity
    override val formFactor: FormFactor = FormFactor.Mobile
    override val useGenericInstrumentedTests = true
    override val useGenericLocalTests = true
    override fun thumb() = Thumb.NoThumb
  }
}