1 /** 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.android.launcher3.util; 17 18 19 import android.text.TextUtils; 20 import android.util.Pair; 21 import android.util.Xml; 22 23 import org.xmlpull.v1.XmlSerializer; 24 25 import java.io.IOException; 26 import java.io.StringWriter; 27 import java.io.Writer; 28 import java.util.ArrayList; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 /** 33 * Helper class to build xml for Launcher Layout 34 */ 35 public class LauncherLayoutBuilder { 36 37 // Object Tags 38 private static final String TAG_WORKSPACE = "workspace"; 39 private static final String TAG_AUTO_INSTALL = "autoinstall"; 40 private static final String TAG_FOLDER = "folder"; 41 private static final String TAG_APPWIDGET = "appwidget"; 42 private static final String TAG_SHORTCUT = "shortcut"; 43 private static final String TAG_EXTRA = "extra"; 44 45 private static final String ATTR_CONTAINER = "container"; 46 private static final String ATTR_RANK = "rank"; 47 48 private static final String ATTR_PACKAGE_NAME = "packageName"; 49 private static final String ATTR_CLASS_NAME = "className"; 50 private static final String ATTR_TITLE = "title"; 51 private static final String ATTR_TITLE_TEXT = "titleText"; 52 private static final String ATTR_SCREEN = "screen"; 53 private static final String ATTR_SHORTCUT_ID = "shortcutId"; 54 55 // x and y can be specified as negative integers, in which case -1 represents the 56 // last row / column, -2 represents the second last, and so on. 57 private static final String ATTR_X = "x"; 58 private static final String ATTR_Y = "y"; 59 private static final String ATTR_SPAN_X = "spanX"; 60 private static final String ATTR_SPAN_Y = "spanY"; 61 62 private static final String ATTR_CHILDREN = "children"; 63 64 65 // Style attrs -- "Extra" 66 private static final String ATTR_KEY = "key"; 67 private static final String ATTR_VALUE = "value"; 68 69 private static final String CONTAINER_DESKTOP = "desktop"; 70 private static final String CONTAINER_HOTSEAT = "hotseat"; 71 72 private final ArrayList<Pair<String, HashMap<String, Object>>> mNodes = new ArrayList<>(); 73 atHotseat(int rank)74 public Location atHotseat(int rank) { 75 Location l = new Location(); 76 l.items.put(ATTR_CONTAINER, CONTAINER_HOTSEAT); 77 l.items.put(ATTR_RANK, Integer.toString(rank)); 78 return l; 79 } 80 atWorkspace(int x, int y, int screen)81 public Location atWorkspace(int x, int y, int screen) { 82 Location l = new Location(); 83 l.items.put(ATTR_CONTAINER, CONTAINER_DESKTOP); 84 l.items.put(ATTR_X, Integer.toString(x)); 85 l.items.put(ATTR_Y, Integer.toString(y)); 86 l.items.put(ATTR_SCREEN, Integer.toString(screen)); 87 return l; 88 } 89 build()90 public String build() throws IOException { 91 StringWriter writer = new StringWriter(); 92 build(writer); 93 return writer.toString(); 94 } 95 build(Writer writer)96 public void build(Writer writer) throws IOException { 97 XmlSerializer serializer = Xml.newSerializer(); 98 serializer.setOutput(writer); 99 100 serializer.startDocument("UTF-8", true); 101 serializer.startTag(null, TAG_WORKSPACE); 102 writeNodes(serializer, mNodes); 103 serializer.endTag(null, TAG_WORKSPACE); 104 serializer.endDocument(); 105 serializer.flush(); 106 } 107 writeNodes(XmlSerializer serializer, ArrayList<Pair<String, HashMap<String, Object>>> nodes)108 private static void writeNodes(XmlSerializer serializer, 109 ArrayList<Pair<String, HashMap<String, Object>>> nodes) throws IOException { 110 for (Pair<String, HashMap<String, Object>> node : nodes) { 111 ArrayList<Pair<String, HashMap<String, Object>>> children = null; 112 113 serializer.startTag(null, node.first); 114 for (Map.Entry<String, Object> attr : node.second.entrySet()) { 115 if (ATTR_CHILDREN.equals(attr.getKey())) { 116 children = (ArrayList<Pair<String, HashMap<String, Object>>>) attr.getValue(); 117 } else { 118 serializer.attribute(null, attr.getKey(), (String) attr.getValue()); 119 } 120 } 121 122 if (children != null) { 123 writeNodes(serializer, children); 124 } 125 serializer.endTag(null, node.first); 126 } 127 } 128 129 public class Location { 130 131 final HashMap<String, Object> items = new HashMap<>(); 132 putApp(String packageName, String className)133 public LauncherLayoutBuilder putApp(String packageName, String className) { 134 items.put(ATTR_PACKAGE_NAME, packageName); 135 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 136 mNodes.add(Pair.create(TAG_AUTO_INSTALL, items)); 137 return LauncherLayoutBuilder.this; 138 } 139 putShortcut(String packageName, String shortcutId)140 public LauncherLayoutBuilder putShortcut(String packageName, String shortcutId) { 141 items.put(ATTR_PACKAGE_NAME, packageName); 142 items.put(ATTR_SHORTCUT_ID, shortcutId); 143 mNodes.add(Pair.create(TAG_SHORTCUT, items)); 144 return LauncherLayoutBuilder.this; 145 } 146 putWidget(String packageName, String className, int spanX, int spanY)147 public LauncherLayoutBuilder putWidget(String packageName, String className, 148 int spanX, int spanY) { 149 items.put(ATTR_PACKAGE_NAME, packageName); 150 items.put(ATTR_CLASS_NAME, className); 151 items.put(ATTR_SPAN_X, Integer.toString(spanX)); 152 items.put(ATTR_SPAN_Y, Integer.toString(spanY)); 153 mNodes.add(Pair.create(TAG_APPWIDGET, items)); 154 return LauncherLayoutBuilder.this; 155 } 156 putFolder(int titleResId)157 public FolderBuilder putFolder(int titleResId) { 158 items.put(ATTR_TITLE, Integer.toString(titleResId)); 159 return putFolder(); 160 } 161 putFolder(String title)162 public FolderBuilder putFolder(String title) { 163 items.put(ATTR_TITLE_TEXT, title); 164 return putFolder(); 165 } 166 putFolder()167 private FolderBuilder putFolder() { 168 FolderBuilder folderBuilder = new FolderBuilder(); 169 items.put(ATTR_CHILDREN, folderBuilder.mChildren); 170 mNodes.add(Pair.create(TAG_FOLDER, items)); 171 return folderBuilder; 172 } 173 } 174 175 public class FolderBuilder { 176 177 final ArrayList<Pair<String, HashMap<String, Object>>> mChildren = new ArrayList<>(); 178 addApp(String packageName, String className)179 public FolderBuilder addApp(String packageName, String className) { 180 HashMap<String, Object> items = new HashMap<>(); 181 items.put(ATTR_PACKAGE_NAME, packageName); 182 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 183 mChildren.add(Pair.create(TAG_AUTO_INSTALL, items)); 184 return this; 185 } 186 addShortcut(String packageName, String shortcutId)187 public FolderBuilder addShortcut(String packageName, String shortcutId) { 188 HashMap<String, Object> items = new HashMap<>(); 189 items.put(ATTR_PACKAGE_NAME, packageName); 190 items.put(ATTR_SHORTCUT_ID, shortcutId); 191 mChildren.add(Pair.create(TAG_SHORTCUT, items)); 192 return this; 193 } 194 build()195 public LauncherLayoutBuilder build() { 196 return LauncherLayoutBuilder.this; 197 } 198 } 199 } 200